無批處理時:busybox find 。-執行
我只能訪問busybox。
我有一個文件夾,如下所示:
prueba/$: ls ./uno ./dos ./tres
每兩個子目錄(uno,dos)都有很多文件(名稱中帶有空格和非 ASCII 字元),我想將它們移到另一個子目錄(tres)。
所以我這樣做了(轉義字元只是因為,確保在複製時不做冗餘,並使用 yes 來替換目錄中已經存在的任何文件
$$ tres $$我以前遇到過 mv -f 的問題):
prueba/$: busybox find . -type f -not \( -path . -o -path ./tres \) -exec sh -c ' yes | mv "$1" ./tres ' sh {} \+
但它只移動它找到的第一個文件,然後退出。
但是如果我執行:
prueba/$: busybox find . -type f -not \( -path . -o -path ./tres \) -exec sh -c ' yes | mv "$1" ./tres ' sh {} \;
我得到了我的預期。所有文件都從子目錄“uno”和“dos”移動到子目錄“tres”。
什麼時候被啟動的內部機制是什麼
;
$$ implicit loop $$和
+
$$ implicit batch processing $$到位了嗎? 第一個命令行(帶有 的命令行+
)有什麼問題?以下是不可能的:
mv -f ./uno/* ./dos/* ./tres/
我正在做一些自動化的工作,這將需要我只執行一個單線並完成這項工作。另外,這是一個無聊的解決方案。
編輯:
背後的原因
find . -exec sh -c 'CMD "$1"' sh {} \;
將其更改為:
find uno/ dos/ -type f -exec sh -c 'exec mv -f "$@" tres/' sh {} +
您的程式碼存在的問題:
find . -not -path ./tres
不排除./tres
,但不排除./tres/any-file-in-it
-exec sh 'mv "$1" tres' sh {} +
呼叫sh
盡可能多的文件作為參數,但您只移動第一個 ($1
)。將所有"$@"
位置參數擴展為單獨的參數,就像您編寫了."$1" "$2" "$3" ... "$*last*"
- 注意
!
作為標準替代非標準-not
- 請注意,這
+
不是任何 shell 中的特殊字元。它不需要被引用。- 請注意避免首先提示的
-f
選項,mv
因此您不需要yes
. 如果您仍然想使用yes
,您可以這樣做yes | find ... -exec sh -c 'exec mv ...
, assh
並將mv
繼承’s stdin 並從那裡find
讀取s 。y
- 通過
mv
GNU coreutils 和最新版本的實現busybox
,您可以sh
使用find ... -exec mv -ft tres {} +
.如果您想從任何目錄(遞歸)移動文件,除了
./tres
目前目錄中的文件和排除文件之外,您需要:LC_ALL=C find . -path ./tres -prune -o \ -path './*/*' -type f -exec sh -c 'exec mv -f "$@" tres/' sh {} +
上面的
-prune
內容告訴find
不要在 內部查找文件./tres
,而對於其他文件,-path './*/*'
(結合LC_ALL=C
so匹配任何字節字元串,而不僅僅是字元)限制為路徑在前導之後*
至少包含一個的文件,因此不包括目前目錄。/``./
與
zsh
:set -o extendedglob # best in ~/.zshrc mv -f -- (^tres)/**/*(D.) tres/
但請注意,如果目前目錄中存在指向目錄的符號連結,它們將被跟踪。如果達到系統對參數的數量和大小的限制,它也可能會失敗(請參閱
zargs
解決方法)。與 相反
find
,zsh
glob 確實對文件列表進行排序,因此如果有多個具有相同名稱的文件,那麼最終./tres
將是哪個文件將更具確定性(這將是其路徑最後排序的文件,但要注意順序排uno
在後面dos
是詞彙¹;所有其他的都將失去)¹您可以添加
n
glob 限定符以獲得數字順序,但這僅適用於數字序列(例如,dir2
之前出現),仍然會在之後排序)dir10``uno``dos