在 Bash 中,我希望根據帶有許多替換字串的預定義字典重命名許多檔案。我有多個檔案嵌套在目錄樹中,例如:
./aa
./b/aa
./b/bb
./c/aa
./c/d/ee
我有一個“sed 腳本” dict.sed,其內容如下:
s|aa|xx|g
s|ee|yy|g
我可以遞回find并使用所述 sed 腳本將匹配 aa 和 ee 的檔案分別重命名為 xx 和 yy 并保留目錄結構嗎?
目前我有:
function rename_from_sed() {
IFS='|' read -ra SEDCMD <<< "$1"
find "." -type f -name "${SEDCMD[1]}" -execdir mv {} "${SEDCMD[2]}" ';'
}
while IFS='' read -r line || [[ -n "${line}" ]]; do
rename_from_sed "$line"
done < "dict.sed"
這似乎可行,但有沒有更好的方法,也許使用而不是逐行sed -f dict.sed決議?dict.sed當前的方法意味著我需要指定分隔符,并且也僅限于確切的檔案名。
最接近的其他答案可能是https://stackoverflow.com/a/11709995/3329384但這也有目錄也可能被重命名的限制。
uj5u.com熱心網友回復:
這似乎很奇怪:迭代 sed 腳本中的行。你要:
我可以遞回查找和重命名檔案嗎
所以迭代檔案,而不是 sed 腳本。
find .... | while IFS= read -r file; do
newfile=$(sed -f dict.sed <<<"$file")
mv "$file" "$newfile"
done
相關https://mywiki.wooledge.org/BashFAQ/001和https://mywiki.wooledge.org/BashFAQ/020
但是有沒有更好的方法
當然 - 不要使用 Bash 并使用 Sed。fork()用 Python 或 Perl 撰寫整個腳本 - 使用無需任何呼叫即可在單個執行緒中執行所有操作的工具將快 1000 倍。
無論如何,您也可以逐行決議 sed 腳本并運行單個find呼叫。
find "." -type f '(' -name aa -execdir mv {} xx ';' ')' -o '(' -name ee -execdir mv {} yy ';' ')'
您必須建立這樣的電話,例如:
findargs=()
while IFS='|' read -r _ f t _; do
if ((${#findargs[@]})); then findargs =('-o'); fi
findargs =( '(' -name "$f" -execdir {} "$t" ';' ')' )
done < "dict.sed"
find . -type f "${findargs[@]}"
uj5u.com熱心網友回復:
假設檔案中的行dict是 的形式from|to,下面是純的實作bash,沒有使用findand sed。
#!/bin/bash
shopt -s globstar nullglob
while IFS='|' read -r from to; do
for path in ./**/*"$from"*; do
[[ -f $path ]] || continue
basename=${path##*/}
echo mv "$path" "${path%/*}/${basename//"$from"/"$to"}"
done
done < dict
--
$ cat dict
aa|xx
ee|yy
echo如果您對輸出感到滿意,請洗掉。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/414671.html
標籤:
