簡體   English   中英

雙引號與Bash中的星號文件名擴展

[英]Double quotes vs asterisk filename expansion in Bash

在目錄~/temp/a/foo/~/temp/b/foo foo/我有一些名為bar1bar2bar bar1bar bar2等的文件。

我正在嘗試編寫一行Bash,將包含“foo”的目錄中的所有這些文件作為名稱的最后一部分復制到相應“foo”文件夾上方的文件夾中。

只要文件名中沒有空格,這是一項簡單的任務,但在處理foo foo目錄時,以下兩個命令會失敗:

for dir in `find . -type d -name '*foo'` ; do cp $dir/* "$(echo $dir|sed 's_foo__g')" ; done

cp命令無法將"foo foo"的最后一個foo視為同一目錄名的一部分。)

for dir in `find . -type d -name '*foo'` ; do cp "$dir/*" "$(echo $dir|sed 's_foo__g')" ; done

"$dir/*"未展開。)

嘗試將$dir/*替換$dir/* "$(echo $dir/*)"嘗試更不成功。

是否有一種簡單的方法來擴展$dir/*以便cp理解?

for循環不僅錯誤 - sed也不適合這項工作。

while IFS= read -r -d '' dir; do
  cp "$dir" "${dir/foo/}"
done < <(find . -type d -name '*foo' -print0)

find (和IFS= read -r -d '' )上使用-print0可確保帶有換行符的文件名不會弄亂你。

使用< <(...)構造確保如果循環內部設置變量,更改目錄狀態或執行類似的操作,那些更改將繼續存在(管道的右側位於bash的子shell中,如此管道進入while循環意味着在while循環中對shell的狀態所做的任何更改都將在其退出時被丟棄。

使用${dir/foo/}比調用sed更有效,因為它在bash內部執行字符串替換。

這里的問題是不是與cp ,而是for ,因為默認情況下它被分割的話你的輸出殼層的,而不是由目錄名。

一個懶惰的解決方法是使用while而是逐行處理目錄列表,如下所示:

find . -type d -name '*foo' | while read dir; do cp "$dir"/* "$(echo $dir | sed 's_foo__g')" ; done

這應該可以解決你的空間問題,但這絕不是一個萬無一失的解決方案。

請參閱Charles Duffy的答案,以獲得更准確的解決方案。

~/temp/b/foo foo/重命名為沒有空格的東西,例如~/temp/b/foo_foo/並做你想要再做的事情。 之后,如果你真的需要,你可以將它重命名為原始空間。 BTW。 我自己從不使用包含空格的文件名,只是為了避免像你現在面臨的那樣復雜化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM