[英]Double quotes vs asterisk filename expansion in Bash
在目錄~/temp/a/foo/
和~/temp/b/foo foo/
我有一些名為bar1
, bar2
, bar bar1
, bar 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.