Bash

bash:用空格移動文件

  • November 20, 2020

當我移動文件名中帶有空格的單個文件時,它的工作方式如下:

$ mv "file with spaces.txt" "new_place/file with spaces.txt"

現在我有一個可能包含空格的文件列表,我想移動它們。例如:

$ echo "file with spaces.txt" > file_list.txt
$ for file in $(cat file_list.txt); do mv "$file" "new_place/$file"; done;

mv: cannot stat 'file': No such file or directory
mv: cannot stat 'with': No such file or directory
mv: cannot stat 'spaces.txt': No such file or directory

為什麼第一個範例有效,而第二個範例無效?我怎樣才能讓它工作?

永遠,永遠使用for foo in $(cat bar). 這是一個典型的錯誤,通常被稱為bash pitfall number 1。您應該改用:

while IFS= read -r file; do mv -- "$file" "new_place/$file"; done < file_list.txt

當您執行循環時,bash 將對它讀取的內容應用分詞,for這意味著a strange blue cloud將被讀取為astrange和:blue``cloud

$ cat files 
a strange blue cloud.txt
$ for file in $(cat files); do echo "$file"; done
a
strange
blue
cloud.txt

相比於:

$ while IFS= read -r file; do echo "$file"; done < files 
a strange blue cloud.txt

甚至,如果您堅持使用UUoC

$ cat files | while IFS= read -r file; do echo "$file"; done
a strange blue cloud.txt

因此,while循環將讀取其輸入並使用read將每一行分配給一個變數。將IFS=輸入欄位分隔符設置為 NULL *,並阻止它解釋反斜杠轉義的-r選項(因此將其視為斜杠 +而不是製表符)。after表示“將–之後的所有內容視為參數而不是選項”,它可以讓您正確處理以開頭的文件名。read``\t``t``--``mv``-


  • 這裡沒有必要,嚴格來說,在這種情況下唯一的好處是read不會刪除任何前導或尾隨空格,但是當您需要處理包含換行符的文件名時,這是一個好習慣,或者通常,當您需要能夠處理任意文件名時。

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