Bash
根據輸入列表複製文件,文件名中的特殊字元
這是基於這裡的問題。
問題:
- 我有一個 .txt 文件,其中列出了我想複製到shell(Mac 終端)中的文件夾newfolder中的文件名。
Approach,其中filelist.txt包含我要複製的文件名(由 \n 分隔):
# version 1 for file in $(cat filelist.txt); do cp "$file" newfolder; done
錯誤:
如果我在filelist.txt中有包含破折號、空格等的文件名,則名稱會被拆分,並且我會正確收到
No such file
錯誤消息。這是我嘗試解決它的方法(向變數添加 dbl 引號):
# version 2 for file in "$(cat filelist.txt)"; do cp "$file" newfolder; done
但這會列印出所有文件名(不會在空格上拆分)並且不會複製任何內容。
問題:
- 如上所述添加引號解決了名稱拆分問題,例如,當我將其提供給
echo
; 為什麼它不起作用cp
?cat
使用and執行此操作的正確方法是什麼cp
?上面連結的答案中的評論表明以下內容:
set -f;IFS=$'\n'
它解決了問題,但我不知道它做了什麼。
任何提示都非常感謝!
有多種選擇;這是一:
cat filelist.txt | while read file; do cp "$file" newfolder done
那麼,首先為什麼
for file in $(cat filelist.txt); do cp "$file" newfolder; done
不行?假設您的文件列表包含
a b c
$(cat filelist.txt)
生成文件名列表。for 循環看到輸出cat
並將其解釋為:for file in a b c ; do
這顯然不是本意。
這就是有關輸入欄位分隔符的註釋的幫助。通常,IFS 是任何空格,因此文件名中的空格將被解釋為文件名之間的分隔符。如果將 IFS 顯式設置為換行符,則空格不再被視為分隔符。
for file in "$(cat filelist.txt)"; do cp "$file" newfolder; done
為 for 循環創建一個參數。結果相當於:
for file in "a b c" ; do
因此,循環只執行一次,文件名不存在。