Альтернативы xargs-l
Я хочу переименовать кучу dir из DIR в DIR.СТАРЫЙ. В идеале я бы использовал следующее:
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".
Каковы некоторые общие альтернативные методы для сбора массива файлов, а затем выполнения на них в сценарии оболочки?
3 ответов
можно использовать -exec
и {}
черт find
команда, поэтому вам не нужны никакие трубы вообще:
find -maxdepth 1 -type d -name "*.y" -mtime +`expr 2 \* 365` -exec mv "{}" "{}.old" \;
Также вам не нужно указать.'path-это значение по умолчанию для find
. И вы использовали дополнительные косые черты в "*.y"
. Конечно, если имена файлов на самом деле не содержат цитаты.
справедливости ради следует отметить, что версия с while read
loop является самым быстрым из предложенных здесь. Вот некоторые примеры измерений:
$ 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 думаю, это потому что find
и xargs
вызывает дополнительный /bin /sh (фактически exec(3)
делает это) каждый раз для выполнения команды, в то время как shell while
петли не.
Upd: если ваша версия busybox была скомпилирована без -exec
опции поддержки затем while
петли или xargs
, предложенный в других ответах (один, два), это ваш путь.
-
использовать
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
-
использовать
sh -c
как команду. Обратите внимание на немного странное использованиечтобы назвать первый аргумент (обычно это будет имя скрипта, и это переходит в
и пока вы подавляете скрипт с
-c
, спор все еще идет к) и
-n 1
чтобы избежать дозирования.find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print0 | xargs -0 -r -n 1 sh -c 'mv -- "" "".old'
редактировать Ой: я забыл о find -exec
снова.
альтернативой является использование цикла:
find . -maxdepth 1 -type d -name \"*.y\" -mtime +`expr 2 \* 365` -print | while IFS= read file
do
mv "$file" "$file".old
done