Bash

如何批量重命名與 Linux 中的模式匹配的所有文件?

  • August 12, 2022

我有一個文件夾,其中包含許多 .mkv我想重命名的文件,而無需手動這樣做。

模式是這樣的:

...
[XVC]_Control_-_10_-_Doctors_[SCB055Y].mkv
[XVC]_Control_-_11_-_Engineers_[50OPZ00].mkv
...

我希望結果是:

...
Control-10-Doctors.mkv
Control-11-Engineers.mkv
...

我已經嘗試通過 and 使用和find管道它,但我似乎無法讓它工作。sed``tr

這是我迄今為止嘗試過的:

find . -iname "*.mkv" -exec sed -e 's/\[[^][]*\]//g' {} \;
find . -type f "*mkv" | sed 's/\[[^][]*\]//g' | tr -d '_'
find . "*.mkv" -type f -print0 | xargs -0 sed -i '' -e 's/\[[^][]*\]//g' | tr -d '_'
find . -iname "*.mkv" -exec rename 's/\[[^][]*\]//g' .mkv '{}' \;
find . -iname "*.mkv" -exec rename -n 's/\[[^][]*\]//g' {} ";"

還有其他幾個,但似乎沒有一個有效。我發現下面的命令命令有效,令人費解:

(input)
echo '[XVC]_Control_-_10_-_Doctors_[SCB055Y].mkv' | sed 's/\[[^][]*\]//g' | tr -d '_'`

(output)
Control-10-Doctors.mkv

編輯:

$ file $(which rename)
/usr/bin/rename: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d7b5a08ee8556c59dbdda26e998e20d4762c2bbc, for GNU/Linux 3.2.0, stripped
rename -n 's/\[.+?\]//g; s/_//g' *mkv
rename: not enough arguments
Try 'rename --help' for more information.

這將與 perl-rename 一起使用(稱為renameorprenameperl-rename取決於您的發行版):

$ rename -n 's/\[.+?\]//g; s/_//g' *mkv
[XVC]_Control_-_10_-_Doctors_[SCB055Y].mkv -> Control-10-Doctors.mkv
[XVC]_Control_-_11_-_Engineers_[50OPZ00].mkv -> Control-11-Engineers.mkv

或者,寫一個小循環:

find . -iname "*.mkv" -print0 |
   while IFS= read -rd '' file; do
       newName=$(printf -- '%s\n' "$file" | perl -pe 's/\[.+?\]//g; s/_//g')
       echo mv -- "$file" "$newName"
   done

如果看起來正確,請刪除echo並再次執行它以實際重命名文件。如果這為您提供了所需的輸出,請再次執行它而不-n實際重命名文件。


由於各種原因,您的命令不起作用。

  1. find . -iname "*.mkv" -exec sed -e 's/\[[^][]*\]//g' {} \;

這是sed在文件本身上執行命令,因此它只會更改文件的內容,而不是名稱。甚至沒有,因為您沒有使用-i這意味著它只是將更改的內容列印到標準輸出。 2. find . -type f "*mkv" | sed 's/\[[^][]*\]//g' | tr -d '_'

在這裡,find正在列印文件名,但這些只是作為文本(流)傳遞給sed它修改其輸入,但不改變文件名。它與 相同echo foo | sed 's/f/b/'foo如果碰巧在那裡,這不會重命名一個名為的文件。 3. find . "*.mkv" -type f -print0 | xargs -0 sed -i '' -e 's/\[[^][]*\]//g' | tr -d '_'

在這裡,sed再次在文件上執行,所以它基本上是相同的,除瞭如果它的任何內容匹配它會實際修改文件。由於這些是二進製文件,您不太可能但並非不可能實際修改它們。 4. find . -iname "*.mkv" -exec rename 's/\[[^][]*\]//g' .mkv '{}' \;

這個實際上能夠重命名文件,但是由於您將字元串.mkv作為第一個參數傳遞給rename命令,它試圖重命名一個名為.mkv. 由於您可能沒有這樣的文件,因此它什麼也不做。第二個參數 ,'{}'被忽略。這會奏效:

find . -iname "*.mkv" -exec rename 's/\[[^][]*\]//g' {} \;

但它會將文件重命名為_Control_-_10_-_Doctors_.mkvand_Control_-_11_-_Engineers_.mkv因為你沒有處理_那個文件。 5. find . -iname "*.mkv" -exec rename -n 's/\[[^][]*\]//g' {} ";"

這個應該有效!就像上面 4 中描述的那樣,它只是沒有進行正確的重命名。

引用自:https://unix.stackexchange.com/questions/713463