Bash
bash:用空格移動文件
當我移動文件名中帶有空格的單個文件時,它的工作方式如下:
$ 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
將被讀取為a
、strange
和: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
不會刪除任何前導或尾隨空格,但是當您需要處理包含換行符的文件名時,這是一個好習慣,或者通常,當您需要能夠處理任意文件名時。