Files
在多個(可變)文件夾中復製文件
我想複製具有可變子文件夾名稱的多個子文件夾中的文件。
例子:
mkdir rootdir mkdir rootdir/dir1 mkdir rootdir/dir2 mkdir rootdir/dir3 touch rootdir/dir1/foo.txt touch rootdir/dir2/foo.txt touch rootdir/dir3/foo.txt
使用已知的子文件夾名稱,我可以單獨複製每個文件。
cp rootdir/dir1/foo.txt rootdir/dir1/bar.txt cp rootdir/dir2/foo.txt rootdir/dir2/bar.txt cp rootdir/dir3/foo.txt rootdir/dir3/bar.txt
但是對於未知數量的子文件夾名稱未知(我知道文件名),我不能再這樣做了。
我可以找到文件…
ls ./**/foo.txt find . -name foo.txt
…但我沒有找到允許將此資訊傳遞到 cp (或替代工具)的語法。
有幾個選項:
find rootdir -type f -name foo.txt -execdir cp {} bar.txt \;
這會搜尋
foo.txt
在 中或下的任何位置呼叫的正常文件rootdir
,當找到一個時,cp
用於將其複製到bar.txt
同一目錄中的名稱。該-execdir
選項是非標準的,但通常實現,並將在找到文件的目錄中執行給定的實用程序。將{}
替換為找到的文件名。或者,
find rootdir -type f -name foo.txt -exec sh -c ' for pathname do cp "$pathname" "${pathname%/*}/bar.txt" done' sh {} +
這基本上做同樣的事情,但呼叫一個
sh -c
包含成批找到的foo.txt
文件的簡短內嵌腳本。循環中的cp
in 會將這些中的每一個複製到與找到的文件相同的目錄中,但路徑名的文件名部分替換為bar.txt
.使用
**
, 正如您在問題中提到的那樣(假設是bash
外殼):shopt -s globstar nullglob dotglob for pathname in rootdir/**/foo.txt; do cp "$pathname" "${pathname%/*}/bar.txt" done
在
bash
中,設置globstar
shell 選項可以使用**
for 遞歸匹配到子目錄,dotglob
並使模式也可以匹配隱藏的名稱。shell 選項使模式完全消失,nullglob
而不是在沒有匹配的情況下保持未擴展。同樣,但使用
zsh
(明確要求正常文件並啟用對 globbing 的等效dotglob
處理nullglob
)bash
:for pathname in rootdir/**/foo.txt(.ND); do cp $pathname $pathname:h/bar.txt done
在這裡,
$pathname:h
將$pathname
與刪除路徑名的文件名部分相同(:h
如“僅頭部”,而不是尾隨位)。