Альтернативы 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