xargs -l的替代品

时间:2012-01-06 14:25:02

标签: bash shell find xargs busybox

我想将一堆dirs从DIR重命名为DIR.OLD。理想情况下,我会使用以下内容:

find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print0 | xargs -0 -r -I file mv file file.old

但我要执行此操作的机器已安装BusyBox且BusyBox xargs不支持“-I”选项。

有哪些常用的替代方法可以收集文件数组,然后在shell脚本中执行它们?

3 个答案:

答案 0 :(得分:9)

您可以使用-exec命令的{}find功能,因此您根本不需要任何管道:

find -maxdepth 1 -type d -name "*.y" -mtime +`expr 2 \* 365` -exec mv "{}" "{}.old" \;

此外,您无需指定'。' path - 这是find的默认值。你在"*.y"中使用了额外的斜杠。当然,如果您的文件名实际上不包含引号。

公平地说,应该注意,带while read循环的版本是此处提出的最快版本。以下是一些示例测量:

$ cat measure 
#!/bin/sh
case $2 in
  1) find "$1" -print0 | xargs -0 -I file echo mv file file.old ;;

  2) find "$1" -exec echo mv '{}' '{}.old' \; ;;

  3) find "$1" | while read file; do
       echo mv "$file" "$file.old"
     done;;
esac
$ time ./measure android-ndk-r5c 1 | wc
   6225   18675  955493
real    0m6.585s
user    0m18.933s
sys     0m4.476s
$ time ./measure android-ndk-r5c 2 | wc
   6225   18675  955493
real    0m6.877s
user    0m18.517s
sys     0m4.788s
$ time ./measure android-ndk-r5c 3 | wc
   6225   18675  955493
real    0m0.262s
user    0m0.088s
sys     0m0.236s

我认为这是因为findxargs每次执行命令都调用额外的/ bin / sh(实际上exec(3)执行它),而shell while循环执行不

更新:如果编译的busybox版本没有-exec命令的find选项支持,则建议while循环或xargs在其他答案中(onetwo),是你的方式。

答案 1 :(得分:2)

  1. 使用for循环。不幸的是,我认为busybox也不会理解read -0,所以你将无法正确处理新行。如果您不需要,最简单的方法就是:

    find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while read file; do mv -- "$file" "$file".old; done
    
  2. 使用sh -c作为命令。注意使用$0稍微奇怪地命名第一个参数(它通常是脚本名称,然后转到$0,当你用-c抑制脚本时,参数仍然存在到$0)并使用-n 1来避免批处理。

    find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print0 | xargs -0 -r -n 1 sh -c 'mv -- "$0" "$0".old'
    
  3. 修改 糟糕:我再次忘记了find -exec

答案 2 :(得分:1)

另一种方法是使用循环:

find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while IFS= read file
do
    mv "$file" "$file".old
done