題:
OSX Bash for loop-文件夾名稱中的空格有問題嗎?
JJarava
2013-12-12 18:25:46 UTC
view on stackexchange narkive permalink

在for循環中返回時,我對如何處理路徑名中的空格感到有些困惑。

合理性:我正在清理從中復製過來的文件夾和文件的權限視窗。大多數文件最終都具有 -rwx ------ -rwxr-xr-x 權限,因此我想執行“ chmod -x * ”,然後選擇“ chmod u + x <folders> ”,因此我嘗試以下操作:

  $ alias getdirs ='find。 -maxdepth 1 -mindepth 1-類型d |為$(getdirs)中的i剪切-c 3-'$; chmod u + x $ i;完成 

,只要目錄名稱中沒有空格,就可以正常工作。

我嘗試了 chmod u的不同排列+ x“ $ i” chmod u + x'$ i'相似,但獲得了我想要的行為,但無濟於事。

如何改進我的bash代碼可以與包含空格的文件夾名稱一起使用嗎?

其目的 是為了能夠從普通文件中刪除“ exec”位(因此 chmod -x * 部分),然後將其還原到目錄以允許進入目錄( chmod u + x <dirname> )。從目前為止的評論和答案中,我認為使用適當的“查找”咒語可能會更容易

為什麼要使用cut-不能只使用-exec?
各自使用管道將一堆命令串在一起,可以作為一種提供基於代碼的邏輯步驟註釋的好方法,而大多數事情可以簡化為諸如find和sed之類的命令中的最少步驟。和`awk`等,許多*經驗不足的* shell修補匠發現流程圖樣式命令鏈更易讀和易懂。
@Mark:我想擺脫輸出開頭的./以獲得“不錯”的輸出,僅此而已
@stuffe-但是您必須處理這個字符串問題,所以我發現兩者都同樣複雜-我的建議是放棄使用shell,並使用更完整的非基於文本的語言-例如python,perl,tcl等
@Mark實際上,這就是“計劃b”。我對Python相當滿意(這是我開發實用程序的首選腳本語言),自從遷移到Mac之後,我已經開發了更多功能,但是我試圖以“ Unix方式”實現。從其他答案中,我認為“要走的路”(不是完整的Python腳本)可能是利用“查找”。將調查並報告
分詞並不是那麼棘手,實際上理解它比避免它更容易。此外,在某些時候,您將不可避免地要編寫一個使用命令行參數的Python程序,這些參數將被分詞。
五 答案:
nohillside
2013-12-12 19:07:16 UTC
view on stackexchange narkive permalink

由於空間充當分隔符的方式,在所有Unix Shell中這類事情都可能很棘手,將別名作為Shell腳本的一部分運行會使事情變得更加有趣。我可能會運行兩遍find命令,以按順序設置目錄,然後再設置文件:

  find。 -maxdepth 1 -mindepth 1-類型d -exec chmod u + x'{}'\; find。 -maxdepth 1 -mindepth 1 -type f -exec chmod u-x'{}'\;  
並回答最初的需求:`查找。 -maxdepth 1 -mindepth 1 -type f -exec chmod u-x'{}'\;`
evilsoup
2013-12-13 00:29:34 UTC
view on stackexchange narkive permalink

通常,將find的輸出解析為bash循環的“正確”方法是使用“讀取時循環”而不是“ for ”循環。在bash中,默認情況下,for循環使用任何空格(空格,製表符,換行符)進行拆分-可以更改,但是使用 read 更容易(在我看來)使用 read 可以讀取一行

  find。 -maxdepth 1 -mindepth 1-類型d |一邊讀我chmod u + x“ $ i”;完成 

請注意,我在那裡引用了“ $ i” -這同樣重要,因為引用變量可以防止shell拆分其內容(相同 for 遇到的問題,但另一方面)。還要注意,您不能使用單引號:'$ i'將返回原義的 $ i ,而不是變量的內容。

這仍然會破壞名稱中帶有換行符的目錄。有一種解決方法涉及find的 -print0 ,但是我只見過專門用於測試腳本的文件名中的換行符。我不知道這是否適用於OSX中的bash版本(取自 greg的Wiki):

  find。 -maxdepth 1 -mindepth 1 -type d -print0 |而IFS =讀取-r -d''i; chmod u + x“ $ i”;完成 

但是,在這種情況下,使用glob更容易:以 / 結尾的glob僅會擴展到目錄,因此您可以

  chmod u + x * /  

(這對於空格,換行符和其他任何東西都可以很好地工作)。更一般而言,要遍歷所有目錄:

 ,用於* /中的f;用“ $ f”做事;完成 

不幸的是,無法在任何版本的bash中僅選擇帶有glob的文件(這是我更喜歡zsh的原因之一,zsh的glob足夠強大,以至於你永遠無法擁有煩擾查找)。

我認為“解析”“ find”的輸出是正確的。在任何情況下,解析“ find”的輸出都不比“ -exec”或“ -execdir”更有效,或者在非常有限的情況下,“ find…-print0 | |”更有效。 xargs -0…`
@kojiro我不同意。您的評論過於幼稚。對於需要長時間搜索的大型結果列表或從大型文件系統收集的查找列表的重複操作,將find的輸出存儲並在單獨的例程中進行處理是有利的,因此您不必重複執行find命令或push單行腳本的局限性。這只是您的論點瓦解的一個例子。還有更多。
@IanC。因此,緩存“ find…-print0”的輸出。另外,我認為緩存未經過處理的文件名列表會*限制單行腳本的局限性。緩存無效問題也不是無關緊要的。
感謝您提出有關使用while循環的建議-它確實可以更好地工作(即,它可以工作)。使用glob擴展的問題是,它不能在“隱藏”目錄(例如.Testdir)下工作,而FIND可以。
@JJarava只需執行`shopt -s dotglob`即可啟用點名稱的glob擴展。
Flavin
2013-12-12 20:54:31 UTC
view on stackexchange narkive permalink

我有兩個建議:

  1. 使用 sed 將所有目錄名稱都用引號引起來。
  2. 將管道插入 xargs ,參數為 -L 1 。這將在stdin的每一行上執行一條命令,從而消除 for 循環。
  3. ol>

    嘗試以下管道:

    find。 -maxdepth 1 -mindepth 1-類型d |切-c 3- | sed's /.*/“ &” /'| xargs -L 1 chmod u + x

實際上,我正在研究直接使用find來直接更改權限並繞過複雜的循環和管道-如果我能夠做到,將在此處發布
kojiro
2013-12-13 01:58:14 UTC
view on stackexchange narkive permalink

問題的癥結在於命令替換會發生單詞拆分,因此其中帶有空格的名稱與單獨的名稱完全無法區分開。 Globbing不受此困難的困擾,因此,如果有一種方法可以識別具有glob的目錄並完全避免命令替換,那麼您將無所事事。並且有:

  chmod -x * chmod u + x * /  

但是即使這樣做也太多了,因為 chmod 具有 X (大寫X)符號標誌,該標誌將可執行位僅應用於已經可執行的目錄和文件。所以您真的可以這樣做:

  chmod -x * chmod u + X *  
stuffe
2013-12-12 18:35:44 UTC
view on stackexchange narkive permalink

您的別名只是將空格拉到了第一位,或者您的for循環只讀取了第一位

您可以通過在命令中添加一些測試註釋來進行測試,別名僅拉出最後找到的目錄以將迭代隔離為1,打印出別名認為其接收的內容,然後回顯變量內容以確保它們匹配:

  jaravj $別名getdirs ='找到。 -maxdepth 1 -mindepth 1-類型d |尾巴-1 |為$(getdirs)中的i剪切-c 3-'jaravj $ getdirsjaravj $;回顯“文件名是” $ i; chmod u + x $ i;完成 

編輯:更改了 do; echo ... echo ... ,因為它阻止了該行的執行

嘗試了您的建議,輸出符合預期:我有一個名為“ ZZPRODUCT數據文件夾”的文件夾,因此FOR的輸出為:文件名是ZZPRODUCTchmod:ZZPRODUCT:沒有這樣的文件或目錄文件名是datachmod:數據:沒有這樣的文件或目錄文件名是folderchmod:文件夾:沒有這樣的文件或目錄
如果您的文件夾名為`ZZPRODUCT data folder`,則@JJarava輸出IS N'T符合您的預期!如果符合預期,則輸出將是“文件名是ZZPRODUCT數據文件夾”,而不是“文件名是ZZPRODUCT”。 Stuffe發現了問題。
如果echo的輸出被截斷,而getdirs的輸出沒有截斷,則問題在thap循環中;如果getdirs被截斷,則問題出在您的別名上。話雖如此,我喜歡@patrix's解決方案,您是否嘗試過?


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...