Альтернативы xargs -l - PullRequest
       54

Альтернативы xargs -l

7 голосов
/ 06 января 2012

Я хочу переименовать группу DIR из 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, а xargs BusyBox не поддерживает опцию -I.

ЧтоКакие-нибудь распространенные альтернативные методы сбора массива файлов и последующего их выполнения в сценарии оболочки?

Ответы [ 3 ]

9 голосов
/ 06 января 2012

Вы можете использовать -exec и {} функции команды find, поэтому вам вообще не нужны никакие трубы:

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

Также вам не нужно указывать '.' путь - это значение по умолчанию для 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

Я думаю, это потому, что find и xargs каждый раз для выполнения команды вызывают дополнительные / bin / sh (фактически exec(3) делает это), в то время как оболочка while loop этого не делает.

Upd: Если ваша версия busybox была скомпилирована без поддержки опции -exec для команды find, тогда цикл while или xargs, предложенный в других ответах ( one) , два ), это ваш путь.

2 голосов
/ 06 января 2012
  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'
    

Редактировать Упс: я снова забыл о find -exec.

1 голос
/ 06 января 2012

Альтернативой является использование цикла:

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