2012-01-06 52 views
7

我想重命名從DIR到DIR.OLD的一堆DIR。理想情況下,我會用以下內容: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」選項。

什麼是一些常見的替代方法來收集文件的數組,然後在shell腳本中執行它們?

+2

什麼是「關於?」這將告訴查找列表完全稱爲「* .y」的文件(引號將被傳遞給find,而*將被shell擴展,它將找不到任何東西並通過無論如何),我懷疑存在。 – 2012-01-06 14:39:31

+0

busybox的各種編譯時選項包括CONFIG_FEATURE_FIND_PRINT0,CONFIG_FEATURE_FIND_EXEC,CONFIG_FEATURE_FIND_EXEC_PLUS,這些方法將會或不會工作,具體取決於* your * copy的編譯細節。 – 2015-12-18 15:36:58

回答

9

可以使用find命令-exec{}功能,所以你並不需要在所有的任何管道:「」

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 

我想這是因爲findxargs調用額外的/ bin/sh的(實際上exec(3)做的話)的執行命令每一次,而外殼while循環沒有。

UPD:如果你的busybox版本沒有-exec選項支持編爲find命令則while循環或xargs,在其他的答案(onetwo)建議,是你的方式。

+0

+1:find命令帶有'-exec'選項。它比'xargs'慢一點,因爲它會爲每個找到的文件執行命令。但是,它的工作原理,並沒有_whitespace_問題,因爲外殼沒有涉及。如果由於空白問題而無法使用'xargs',請使用'-exec'。循環與'-exec'參數一樣低效,因爲它們爲每個文件執行一次,但是具有'xargs'具有的空白問題。 – 2012-01-06 15:22:16

+1

在這種情況下'xargs'也爲每個文件執行命令,所以'find'不會變慢。 – 2012-01-06 16:34:58

+0

你說得對。我沒有看這個命令。通常你使用xargs而不是'-exec',因爲xargs在命令行中組合儘可能多的文件,並且只執行幾次命令。 – 2012-01-06 20:56:15

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'使用換行符作爲分隔符。無論你需要'讀-0'(但我不確定它是否在busybox中實現),或者你只需​​要'-print'。 – 2012-01-06 14:36:49

+0

同意。我已經更新了我的答案。 – dogbane 2012-01-06 14:43:26

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。但是你的循環工作 – 2015-12-18 14:59:22