2012-01-06 2 views
7

Я хочу переименовать кучу dirs из DIR в DIR.OLD. В идеале я хотел бы использовать следующее:Альтернативы xargs -l

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» вариант.

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

+2

Что такое «about»? Что скажет find для списка файлов, называемых точно '' * .y "' (кавычки будут переданы для поиска, а в то время как * будет расширяться оболочкой, он ничего не найдет и пройдет во всяком случае), что я сомневаюсь в существовании. –

+0

Среди различных вариантов времени компиляции для busybox: 'CONFIG_FEATURE_FIND_PRINT0',' CONFIG_FEATURE_FIND_EXEC', 'CONFIG_FEATURE_FIND_EXEC_PLUS' - подходы будут работать или не будут работать в зависимости от того, как именно была скомпилирована ваша * копия. –

ответ

9

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

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

Также вам не нужно указать «» path - это значение по умолчанию для 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 вызывают дополнительный/бен/ш (фактически exec(3) делает это) каждый раз, когда для выполнения команды, в то время как оболочка while цикла нет.

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

+0

+1: команда find поставляется с опцией '-exec'. Это немного медленнее, чем 'xargs', потому что он выполняет команду для каждого найденного файла. Но он работает, и он не имеет проблем с _whitespace_, потому что оболочка не задействована. Если вы не можете использовать 'xargs' из-за проблем с пробелами, используйте' -exec'. Петли так же неэффективны, как и параметр '-exec', поскольку они выполняются один раз для каждого файла, но имеют проблемы с пробелами, которые имеют« xargs ». –

+1

'xargs' также выполняет команду для каждого файла в этом случае, поэтому' find' не медленнее. –

+0

Вы правы. Я не смотрел на команду. Обычно вы используете xargs вместо '-exec', потому что xargs объединяет в командной строке столько файлов, сколько может, и выполняет команду только несколько раз. –

1

В качестве альтернативы можно использовать цикл:

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

'read' использует новую строку как разделитель. Либо вам нужно 'read -0' (но я не уверен, что он реализован в busybox), либо вам нужен только' -print'. –

+0

согласился. Я обновил свой ответ. – dogbane

2
  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.

+0

Busybox даже не понимает print0. Но ваш цикл whie работает –