Rename

使用 mv 重命名多個文件以更改副檔名

  • May 7, 2020

我想重命名文件以更改其副檔名,有效地完成

mv *.txt *.tsv

但是當我這樣做時,我得到:

*.tsv 不是目錄

我覺得前 10 個Google熱門節目mv應該像這樣工作有點奇怪。

當您發出命令時:

mv *.txt *.tsv

如果有任何匹配的文件(包括目錄),假設 bash,shell會擴展萬用字元。文件列表被傳遞給程序,在這裡。如果未找到匹配項,則通過未擴展的版本。mv

再說一遍:shell擴展了模式,而不是程序。


大量範例可能是最好的方法,所以我們開始吧:

範例 1:

$ ls
file1.txt file2.txt

$ mv *.txt *.tsv

現在mv線上上發生的事情是外殼擴展*.txt到匹配的文件。因為沒有*.tsv未更改的文件。

mv命令使用兩個特殊參數呼叫

  • argc:參數的數量,包括程序。
  • argv:參數數組,包括作為第一個條目的程序。

在上面的例子中,這將是:

argc = 4
argv[0] = mv
argv[1] = file1.txt
argv[2] = file2.txt
argv[3] = *.tsv

mv程序檢查最後一個參數是否*.tsv是目錄。因為它不是,程序不能繼續,因為它不是為連接文件而設計的。(通常將所有文件合二為一。)也不要一時興起創建目錄。

結果它中止並報告錯誤:

mv: target ‘*.tsv’ is not a directory

範例 2:

現在,如果您改為說:

$ mv *1.txt *.tsv

mv命令通過以下方式執行:

argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[2] = *.tsv

現在,再次mv檢查是否*.tsv存在。因為它沒有將文件file1.txt移動到*.tsv. 也就是說:文件被重命名為*.tsv星號和所有。

$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’

$ ls
file2.txt *.tsv

範例 3:

如果你改為說:

$ mkdir *.tsv
$ mv *.txt *.tsv

mv命令通過以下方式執行:

argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[1] = file2.txt
argv[2] = *.tsv

由於*.tsv現在是一個目錄,文件最終被移動到那裡。


現在:使用命令,例如some_command *.tsv當意圖實際保留萬用字元時,應該始終引用它。如果應該有任何匹配項,通過引用可以防止萬用字元被擴展。例如說mkdir "*.tsv"

範例 4:

如果您這樣做,可以進一步查看擴展,例如:

$ ls
file1.txt file2.txt

$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists

範例 5:

現在:該mv命令可以並且確實可以處理多個文件。但是如果有兩個以上,最後一個必須是目標目錄。(您可以選擇使用該-t TARGET_DIR選項,至少對於 GNU mv。)

所以這沒關係:

$ ls -F
b1.tsv  b2.tsv  f1.txt  f2.txt  f3.txt  foo/

$ mv *.txt *.tsv foo

這裡mv會被呼叫:

argc = 7
argv[0] = mv
argv[1] = b1.tsv
argv[2] = b2.tsv
argv[3] = f1.txt
argv[4] = f2.txt
argv[5] = f3.txt
argv[6] = foo

並且所有文件最終都在目錄中foo


至於你的連結。您提供了一個(在評論中),其中mv根本沒有提到,但是rename. 如果你有更多的連結,你可以分享。以及您聲稱表達這一點的手冊頁。

我知道這並不能回答您的問題,但是如果您正在尋找與解決方法循環相比重命名文件的另一種方法,為什麼不使用find? 我已經多次使用此命令來替換包含數十萬個文件的大型目錄中的文件副檔名。這應該適用於任何符合 POSIX 的系統:

find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;

命令分解:

  1. .’ => 從目前目錄開始的搜尋路徑,由 ’ 標記。'
  2. -name=> 設置查找匹配名稱(在這種情況下所有以 結尾的文件 .gappedPeak
  3. -exec=> 在每場比賽中執行以下命令
  4. sh -c=> ’exec’ 為每個匹配創建一個獨立的 shell 環境
  5. mv "$1" "${1%.gappedPeak}.bed"=>mv第一個變數(由**$1表示),即目前文件名,改為新名稱。在這裡我進行子字元串匹配並刪除;所以再次取第一個 var,$1**並用於從字元串%中刪除。.gappedPeak最後.bed的 只是連接剩餘的變數,在下面的範例中,它現在是, 和,創建新的文件名。test*Number*``.bed``test*Number*.bed
  6. 下劃線是**$0的佔位符**
  7. 被命令找到{}的每個 ( *.gappedPeak) 文件名替換find,並成為命令的**$1**sh
  8. \;標記-exec命令的結束。您也可以使用';'";"

例子:

[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak

[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed

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