Bash

如何批量重命名包含空格的文件/目錄?

  • February 16, 2022

如何通過替換文件/目錄名稱中的片段來批量重命名許多文件和/或f o o目錄b a r

對於每種建議的方法,最好回答以下問題。

  • 是否可以在進行實際重命名之前預覽命令的結果?如何?
  • 該方法是否僅適用於前綴,僅適用於後綴,還是不適用?
  • 重命名是只影響目錄、只影響文件,還是同時影響目錄和文件?
  • 子目錄中的文件/目錄也會被重命名嗎?

替換前綴,範例

為了使任務更具體一點,假設文件

o l d prefix file 1.c

o l d prefix file 1.h

o l d prefix file 2.c

o l d prefix file 2.h

應該重命名為

n e w prefix file 1.c

n e w prefix file 1.h

n e w prefix file 2.c

n e w prefix file 2.h

還假設在同一目錄中有(子)目錄名為

o l d prefix, dir 1 _

o l d prefix, dir 2 _

這些目錄也會被重命名嗎?

你能調整你的方法來只重命名目錄(而不是文件)嗎?

或者只重命名文件(而不是目錄)?

替換後綴

還可以考慮重命名文件中的後綴,以便將

file 1, o l d suffixandfile 2, o l d suffix分別重命名為

file 1, n e w suffixand file 2, n e w suffix

對於目錄也是如此。

dir 1., o l d suffix將和分別重命名dir 2., o l d suffix

dir 1., n e w suffixdir 2., n e w suffix

推薦的方法?

你會推薦什麼重命名方法?

筆記

請注意,向名稱添加前綴或後綴只是更通用替換前綴或後綴的一種特殊情況,即原始前綴或後綴恰好是空字元串的情況。類似地,去除前綴或後綴的情況也是替換前綴或後綴的一種特殊情況,即新的前綴或後綴為空字元串的情況。

更多需要考慮的問題

我知道在重命名文件時還需要考慮其他更高級的問題,例如添加或刪除日期或序列號和/或以下參考文獻中最後五個問題中的主題。

我邀請您提出有關重命名文件/目錄(或符號連結)的任何問題,並在您的答案中建構一個合適的範例。

寫答案時,不要覺得你必須回答這裡提出的所有案例!如果您願意,請

隨意只關註一個特定案例(上述案例之一,或您選擇的其他案例)。

參考

0. 針對通用解決方案1

為了方便我未來的自己和其他讀者,我將專注於通用解決方案。

為簡單起見,我假設在任何文件/目錄名稱 中都沒有引號——沒有雙引號 ( ") 和單引號 ( )。2'

作為第一個範例,我將展示如何使用模式重命名文件

o l d prefix file *.*to

n e w prefix file *.*

從而即使文件名中有空格也可以重命名前綴。

我也對重命名目錄感興趣,因此會考慮將目錄

o l d prefix, dir 1 _和分別重命名o l d prefix, dir 2 _

n e w prefix, dir 1 _n e w prefix, dir 2 _

其次,我將展示如何替換後綴。例如,文件

file 1, o l d suffixfile 2, o l d suffix分別重命名為

file 1, n e w suffixfile 2, n e w suffix

同樣,我想看看這如何影響(或不影響)目錄。

因此,我還將檢查目錄

dir 1., o l d suffix和是否dir 2., o l d suffix分別重命名為

dir 1., n e w suffixdir 2., n e w suffix。 3

所有上述文件和目錄都可以在 zip 文件中找到:http:

//user.it.uu.se/~hesc0353/Files-&-dirs-SEunix-A690768.zip。 4

筆記。

以下echo解決方案中出現 表示不會發生重命名。這是一種在您決定進行重命名之前預覽
重命名 的既定技術。 一旦預覽看起來正常,只需刪除並再次執行命令以執行實際重命名。 5
echo

1. 使用 for 循環的通用解決方案

重命名前綴意味著替換o l d prefixn e w prefix: 6

for f in "o l d prefix"*; do\
echo mv "$f" "n e w prefix""${f#o l d prefix}"; done

我選擇搜尋以 . 開頭的文件o l d pref

要重命名後綴,請嘗試:

for f in *"l d suffix"; do\
echo mv "$f" "${f%o l d suffix}""n e w suffix"; done

重命名是只影響目錄、只影響文件,還是同時影響目錄和文件?

– 此方法更改文件和目錄的名稱。

如果這不是您想要的,請嘗試find ... -type ... -exec 下一節中的方法。

子目錄中的文件/目錄也會被重命名嗎?

– 不會。使用上述命令之一作為模板不會影響任何子目錄中的文件/目錄。如果你想這樣做,你將不得不有目的地對方法進行相當多的調整。

例如,請參閱此答案中的第一個解決方案。

2.使用的通用解決方案find ... -exec mv

下面的find ... -exec mv方法使您可以選擇僅重命名文件僅重命名目錄*-*通過-type標誌。它也可以被調整以控制命令應該在子目錄樹中搜尋文件或目錄的深度——通過 -maxdepth標誌。

重命名前綴

以下命令替換o l d prefixn e w prefix,但 僅適用於目錄。每個文件都可以在單獨的子 shell 中重命名,但通過在內部有一個 for 循環(並用而不是-exec關閉),命令執行效率更高:-exec``sh {} +``{} \;

find . -maxdepth 1 -type d -name "o l d pr*" -exec sh -c\
'for n; do echo mv "${n#./}" "n e w pre${n#./o l d pre}"; done' sh {} +

如果您只想重命名文件,只需使用-type f而不是 -type d(容易記住:f用於文件,d用於目錄)。

重命名後綴

同樣,這裡是如何替換大量文件中的**後綴

find . -maxdepth 1 -type f -name "*d suffix" -exec sh -c\
'for n; do echo mv "$n" "${n%o l d suffix}n e w suffix"; done' sh {} +

解釋

  • find .在目前目錄及其子目錄中搜尋。
  • -maxdepth 1不要在任何子目錄中搜尋*。*
  • -type f僅查找文件(排除目錄)。
  • -name "*d suffix"僅搜尋以 . 結尾的文件d suffix
  • -exec sh -c '...'在子 shell 中執行,允許命令替換,$(...).
  • -exec sh -c 'for n; do mv ...' sh {} +比做

-exec sh -c 'mv ...' {} \;同樣事情的效率更高。 7

  • {}持有任何find發現。
  • echo輸出命令的結果——當你對結果滿意時,

刪除echo並再次執行命令。

  • mv "sou rce" "dest in"執行實際的重命名,用新名稱

替換舊名稱。sou rce``dest in

重命名文件目錄

要一次性重命名文件目錄,只需省略-type

find . -maxdepth 1 -name "o l d pr*" -exec sh -c\
'for n; do echo mv "${n#./}" "n e w pre${n#./o l d pre}"; done' sh {} +

子目錄中的文件/目錄也會被重命名嗎?

-maxdepth 1子句確保子目錄樹中的任何文件/目錄都不會受到影響。

如果您故意要為所有 子目錄中的所有文件重命名後綴,這裡有一個範例:

find . -type f -name "*d suffix" -exec sh -c\
'for n; do echo mv "$n" "${n%o l d suffix}n e w suffix"; done' sh {} +

一句警告。

此方法不適用於在一個命令中重命名許多不同子目錄中的前綴。

3.使用Perl重命名的解決方案

本節專門針對那些 在您的系統上安裝了由 Larry Wall 重命名的 Perl (或知道如何安裝它)的人。 8

rename我喜歡將Perl-script 重命名為的謹慎做法,prename以避免將其與 Linux rename混淆。

該方法是否僅適用於前綴,僅適用於後綴,還是不適用?

您無需擔心是重命名前綴還是後綴,這一事實使 Perl 重命名易於使用。

例如,要替換o l d prefixn e w prefix,請執行以下操作:

prename -n 's/o l d prefix/n e w prefix/' ./"o l d p"*

-n標誌產生預覽的地方。

一旦結果是您想要的,只需刪除-n標誌並再次執行命令。

重命名是只影響目錄、只影響文件,還是同時影響目錄和文件?

與第 1 節的 for-loop 方法一樣,執行prename將重命名目錄文件。

if -f但是,您可以通過在重命名字元串的末尾 添加來選擇僅重命名文件(不包括目錄) ,如下所示: 9

prename -n 's/o l d prefix/n e w prefix/ if -f' ./"o l d p"*

如果您只想重命名目錄(排除文件),請使用 if !-f

prename -n 's/o l d prefix/n e w prefix/ if !-f' ./"o l d p"*

子目錄中的文件/目錄也會被重命名嗎?

我發現 - 當使用正斜杠 ( /) 作為分隔符時 - Perl rename 將僅重命名目前工作目錄中的文件/目錄,而不是任何子目錄中的文件/目錄。

如果您使用其他字元作為分隔符,您實際上可以prename用來重命名子目錄樹中的文件/目錄。這個答案

的第二個解決方案是這種相當非正統的做法的一個例子。

更正常的做法是find ... -execdirprename.

對於這樣的範例,請參閱 此答案

4.重命名文件或目錄的其他好方法

如果您不喜歡上述任何方法,請考慮使用 sedor awk(可能與 結合使用xargs)。

參考


1在測試這個答案中提供的命令/解決方案時,我既沒有使用過正版Linux,也沒有使用正版Unix,而是Windows 10 上的MSYS2,可以說是在Microsoft Windows 上執行的仿真arch-Linux。當然,對於像我這樣的 Windows 使用者來說,一個可行的替代方案是使用 Windows Subsystem for Linux (WSL)

我使用 MSYS2 是因為我覺得它方便易用。

2如果有疑問,在考慮任何重命名之前,請檢查

命令的結果ls *\"*ls *\'*.

或者更好的是:find . -name '*"*'find . -name "*'*"

我認為,在文件/目錄名稱中使用引號肯定是自找麻煩。

此答案列出了文件/目錄名稱中禁止使用的字元。

– 對於 Linux/Unix,只有一個禁止字元:正斜杠 ( /)。

3我的目標不是一次性更改前綴和後綴的解決方案,如 Renaming files with Bash, remove prefix and suffix問題中所要求的那樣。(如果您需要同時重命名前綴和後綴,我建議在一個命令中替換其中一個,然後在另一個命令中替換另一個。)

4我鼓勵讀者下載 zip 文件並將其解壓縮到某個(空)目錄,然後嘗試我在此答案中提供的所有命令。

5對於包含空格的文件和目錄,預覽可能看起來不正確,因為它缺少周圍的雙引號 ( ")。刪除echo仍然會使命令正確執行。

(不要太從字面上理解預覽!)

6我使用反斜杠 ( \) 對長命令進行換行,這樣讀者就無需水平滾動。當您自己建構一個具體範例時,我建議刪除反斜杠並將整個命令寫在一行中。

7要了解更多關於 和 之間的區別{} +{} \;請參閱例如 如何終止由-exec(及其引用)呼叫的 shell 命令。

8嘗試在您的終端中 輸入rename或(然後點擊)。如果安裝了 Perl rename,預計會看到 或類似的東西 - 其中包含該單詞。 如果未安裝,預計會看到類似 . 您可以嘗試的另一件事是.prename``Enter``Usage: rename [-v] [-n] [-f] perlexpr [filenames]``perlexpr
bash: prename: command not found
which prename

9 該評論說該 if -f子句還將重命名符號連結。如果不重命名符號連結,

它建議使用。if (-f && ! -l)

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