題 如何在Linux下創建文本文件中以行命名的文件


我有一個文本文件,其中包含一個項目列表(每行一個),我需要在給定目錄中為所述列表中的每個條目創建一個文件;這些文件中的每一個都應該用所述列表中的字符串命名。此外,如果可能,在文本文件中包含的字符串之後,應將自定義文本附加到文件名。

我應該使用哪些命令從命令行執行此操作?我想 catgrep 和 touch (有可能 xargs?)應該參與這個過程,但經過幾次試驗後我仍然找不到正確的語法。

有人可以告訴我這件事嗎?


6
2018-05-01 21:07


起源




答案:


說你有 list.txt 像這樣:

file 1
file 2
file 3

你可以實現你想要的:

while read FILE; do touch "${FILE} some string"; done < list.txt

9
2018-05-01 21:20



為什麼 ... < list.txt 而不是 cat list.txt | ...?承認後者產生了一個 cat 前者沒有的過程,但它的表現也更加可預測,並且除了......之外更加清晰。 - Aaron Miller
重定向集成在Bash中,沒有必要使用 cat 這裡。如果您願意,可以在命令之前編寫重定向: < list.txt while ...。你能詳細說明嗎? “但它的表現也更加可預測”? - cYrus
ISTR過去遇到麻煩 < file 要么 < `command` 實際上並沒有在它所針對的命令的標準輸入上產生任何東西,直到我放棄試圖讓它完全工作 - 因此我的默認為 cat file | 在我的回答中。不久之前,這可能只是我不知道自己在做什麼;我應該再試一次。 - Aaron Miller
那說, < list.txt while read FILE...done 仍然只是看錯了。我知道它不是,但看起來應該如此。 :) - Aaron Miller


所以你有一個文件 list 其中包含:

this
that
the-other

並且您希望為該文件中的每一行創建一個在該行上給出名稱的文件。這很簡單 - 當且僅當每行只包含一個單詞時:

cat list | xargs touch --

(該 -- 告訴 touch 不要試圖解析任何事後作為論點;沒有它,如果你有像這樣的文件名 -this,領先 - 將觸摸混淆為思考't','h','i'和's'是作為參數,而不是要接觸的文字文件名的一部分。)

這是一個簡單的案例,但它並不是你所問的;如果你想讓文件名包含超出行中指定的文本 list事情變得更複雜; xargs不能做那種插值。相反,你需要類似下面的東西(這需要你的shell bash,這是大多數係統的標準):

for file in `cat list`; do touch -- $file-customtext; done

請注意,只有每行只包含一個單詞時,這仍然有效。在這個命令中, $file 由在給定行中指定的文件名替換 list;它周圍的一切都是字面意思,所以這個命令與 list 上面的內容將創建以下文件:

this-customtext
that-customtext
the-other-customtext

當然,您可以將'-customtext'替換為您喜歡的任何內容,並且您還可以使用前綴和後綴;如果你反而擁有 do touch -- some-$file-text例如,它也可以正常工作,並導致文件命名 some-this-text &C。

那麼,現在,假設的內容 list 並非如此簡單 - 具體而​​言,它們包含空格,非單詞字符或shell無法正確解釋的其他內容。如果你問三個人在這種情況下他們推薦什麼,你可能會得到五個答案;我是Perl黑客,所以我的回答是Perl。具體來說,讓我們假設一個 list 包含:

This is the first line
of three (three?) lines
in the list file.

我這樣做的方式是:

cat list | perl -ne'chomp; system(qq|touch -- "custom $_ text"|)'

這會產生生成的文件:

custom This is the first line text
custom of three (three?) lines text
custom in the list file. text

在這種情況下,自定義文本可以是您喜歡的任何內容,空格和所有,只要它不包含 " (這會讓人困惑 touch)也不是 ' (這會讓人困惑 perl);在Perl命令中, $_ 表示給定行的內容 list,自定義文本屬於它之前或之後,但在雙引號內。 (雙引號之外的自定義文本將被視為 touch作為一個單獨的文件名,除非它包含某些原因,否則將逐字創建 touch 出錯。)


7
2018-05-01 21:22



不!顯然當你 for 跨越線 bash,它將任何空格作為行分隔符,而不僅僅是 \n。我知道 bash 奇怪而挑剔,但是......無論如何,我已經通過一個小命令行Perl更新了處理這種情況的答案。 - Aaron Miller
另外,僅僅是FYI,在反引號中包含一個字符串(`),大多數你可以做到這一點的地方,將把字符串作為一個命令,其結果在其位置插入,如 for 在我的回答中構建。 - Aaron Miller
請閱讀: 為什麼你不應該用for讀取行  - 沒有必要 perl 變通辦法或 cat真的,你只需要使用一個 while read 而是構建。 Bash並不挑剔,只是對待 whitespace作為參數分隔符。 - slhck
Bash需要一段時間習慣,但通常有一種標準的方法來做你必須學習的東西,然後適用於所有地方:) Bash FAQ 幾乎涵蓋了所有情況。 - slhck
@Sekhemty我真的建議不要使用這樣的解決方法。 Bash可以很好地處理名稱中帶有空格的文件,你只需要使用正確的命令(參見下面的cYrus'答案)。人們對Bash的許多問題源於他們發現的“錯誤”命令 for 循環迭代文件。這些在許多情況下都可以正常工作,但對其 - slhck