[英]Rename files in linux with regex
這實際上不是問題,我自己解決了。 但是我想在這里發布我的解決方案,以在相同情況下節省其他人的時間和精力。
因此,我不得不重新命名很多(+3000)以匹配特定模式的情況。 在我的情況下,文件是同步的自動備份,因此文件將被重命名,如下所示:
foo.bar -> foo~20150221-1330.bar
經過大量的論壇和手冊頁搜索后,我創建了以下單行代碼,該代碼使用linux中的find, sed
, xargs
和mv
命令恢復了原始文件名:
find . -type f | sed -e 'p;s/\(.*\)~20[0-9]\{6\}-[0-9]\{6\}\(.*\)/\1\2/' | xargs -n2 -d'\n' mv
如果您願意,可以用自己的樣式替換sed
-part。 該命令可以通過空格(由於xargs
的-d'\\n'
標志)來處理空格,但不能使用換行符。 我希望某些人覺得此命令有用。
好的,我將為每個命令提供更多信息:
find
:給出當前目錄中的所有常規文件(不是目錄) sed
: p
將打印stdin中的每一行, s/regex/regex/
將打印相同的行,但是被替換。 因此,您得到每個文件后跟固定的文件名:
./foo/bar~20150221-172703.txt ./foo/bar.txt`
xargs
: -n2
將使用兩行並將其作為參數發送到mv
,-d'\\ n'將解決文件夾名稱中的空格問題(定界符設置為換行符而不是空格) 您的回答很好,但是如果您還想處理還包含換行符的文件名,或者您不想使用sed
並且要確保僅考慮具有與該模式匹配的基本名稱的文件(您的方法失敗,例如,使用dir~20150221-172703/file
,並且當文件名與您的模式不匹配時,您的方法使mv
抱怨file
和file
是同一文件),您需要稍作不同。
一種可能的情況是,如果您的find
支持-print0
選項(GNU find
則支持):讓find
吐出所有文件名,並使用while
循環,其中Bash(未sed
)將執行替換。 像這樣:
find . -type f -print0 | while IFS= read -r -d '' file; do
dirname=${file%/*}
basename=${file##*/}
# Perform the substitution only on basename
# Since you like regex, you can use them
if [[ $basename =~ ^(.*)~20[0-9]{6}-[0-9]{6}(.*)$ ]]; then
new_basename=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
echo mv "$dirname/$basename" "$dirname/$new_basename"
fi
done
您還可以通過使用-regex
過濾器(不是POSIX,但GNU find
支持它)來確保只find
匹配文件。
find . -regextype posix-basic -regex '.*~20[0-9]\{6\}-[0-9]\{6\}[^/]*' -type f
不確定是否可以完全回答您的問題,但至少可以解決您的方法所存在的缺陷。
沒有GNU好吃的東西,要擁有堅固而干凈的東西就更加困難了。
您可以使用rnm :
rnm -rs '/(.*)~20[0-9]{6}-[0-9]{6}(.*)/\1\2/' -fo -dp -1 *
-fo
:僅文件模式 -dp
:目錄深度(-1表示無限深度,即轉到所有子目錄)。 不過,您可以完全使用自己的正則表達式模式,在這種情況下,您必須將正則表達式模式更改為基本(BRE):
rnm --regex basic -rs '/\(.*\)~20[0-9]\{6\}-[0-9]\{6\}\(.*\)/\1\2/' -fo -dp -1 *
注意:
/
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.