Альтернативы 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, предложенный в других ответах (один, два), это ваш путь.


  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 как команду. Обратите внимание на немного странное использование чтобы назвать первый аргумент (обычно это будет имя скрипта, и это переходит в и пока вы подавляете скрипт с -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