bash xargs -l 的替代方案
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8759285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Alternatives to xargs -l
提问by eatloaf
I want to rename a bunch of dirs from DIR to DIR.OLD. Ideally I would use the following:
我想将一堆目录从 DIR 重命名为 DIR.OLD。理想情况下,我会使用以下内容:
find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print0 | xargs -0 -r -I file mv file file.old
But the machine I want to execute this on has BusyBox installed and the BusyBox xargs doesn't support the "-I" option.
但是我想在其上执行此操作的机器安装了 BusyBox 并且 BusyBox xargs 不支持“-I”选项。
What are some common alternative methods for collecting an array of files and then executing on them in a shell script?
收集文件数组然后在 shell 脚本中对它们执行的一些常见替代方法是什么?
回答by praetorian droid
You can use -execand {}features of the findcommand so you don't need any pipes at all:
您可以使用命令的-exec和{}功能,find因此根本不需要任何管道:
find -maxdepth 1 -type d -name "*.y" -mtime +`expr 2 \* 365` -exec mv "{}" "{}.old" \;
Also you don't need to specify '.' path - this is default for find. And you used extra slashes in "*.y". Of course if your file names do not really contain quotes.
你也不需要指定 '.' 路径 - 这是find. 并且您在"*.y". 当然,如果您的文件名实际上不包含引号。
In fairness it should be noted, that version with while readloop is the fastest of proposed here. Here are some example measurements:
公平地说,应该注意的是,带有while read循环的版本是这里提出的最快的版本。以下是一些示例测量:
$ cat measure
#!/bin/sh
case in
1) find "" -print0 | xargs -0 -I file echo mv file file.old ;;
2) find "" -exec echo mv '{}' '{}.old' \; ;;
3) find "" | 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
I think it's because findand xargsinvokes additional /bin/sh (actually exec(3)does it) every time for execute a command, while shell whileloop do not.
我想这是因为find与xargs所调用额外的/ bin / sh的(实际上exec(3)确实是)为执行命令每一次,而壳while循环不。
Upd:If your busybox version was compiled without -execoption support for the findcommand then the whileloop or xargs, suggested in the other answers (one, two), is your way.
更新:如果您的 busybox 版本是在没有-exec选项支持find命令的情况下编译的,那么在其他答案(一、二)中建议的while循环或就是您的方式。xargs
回答by Jan Hudec
Use a
forloop. Unfortunately I don't think busybox understandsread -0either, so you won't be able to handle newlines properly. If you don't need to, it's easiest to just:find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while read file; do mv -- "$file" "$file".old; doneUse a
sh -cas the command. Note the slightly weird use of$0to name the first argument (it would normally be the script name and that goes to$0and while you are suppressing script with-c, the argument still goes to$0) and the use of-n 1to avoid batching.find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print0 | xargs -0 -r -n 1 sh -c 'mv -- "
" "find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while read file; do mv -- "$file" "$file".old; done
".old'find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print0 | xargs -0 -r -n 1 sh -c 'mv -- "
" "##代码##".old'find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while IFS= read file do mv "$file" "$file".old done
使用
##代码##for循环。不幸的是,我认为busybox 也不理解read -0,因此您将无法正确处理换行符。如果您不需要,最简单的方法是:使用 a
##代码##sh -c作为命令。请注意$0命名第一个参数的稍微奇怪的用法(它通常是脚本名称,$0并且当您使用 抑制脚本时-c,参数仍然转到$0)以及使用-n 1避免批处理。
EditOops: I forgot about the find -execagain.
编辑糟糕:我又忘记find -exec了。
回答by dogbane
An alternative is to use a loop:
另一种方法是使用循环:
##代码##
