Bash

根據輸入列表複製文件,文件名中的特殊字元

  • August 10, 2018

這是基於這裡的問題。

問題

  • 我有一個 .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

因此,循環只執行一次,文件名不存在。

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