如何在find ... -exec
中轉義sed
中的反斜杠?
我想更改不同子目錄中某些文件中的一行。這些文件將始終具有副檔名
.dct
,並且它們將始終位於mod
工作目錄的另一個子目錄中呼叫的子目錄中(但是有很多mod
子目錄,所以我使用find
)。但我要更改的字元串是目錄(Windows -> Unix)。我可以使用
find . -type f -path '*/mod/*.dct
. 我試過用sed -e 's/cd c:\\project\\data\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod
.我將其縮小到逃脫的反斜杠是罪魁禍首。這有效:
find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c://' $(basename {}) > $(basename {}).mod"
這不會:
find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"
這是錯誤
sed: -e expression #1, char 7: unterminated `s' command
該
char 7
部分讓我認為轉義存在一些問題。看起來是這樣,但我不知道如何解決它。為了說明,這有效:find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"
所以它看起來像是
sed -e 's/c:\\///'
被轉義為“c:\/
用任何東西替換”並且sed -e 's/c:\\//'
被轉義為“c:\/
用……替換”(這會引發錯誤)而不是“c:\
用任何東西替換”。注意:使用
-execdir
andbasename
而不是-exec
可能有點矯枉過正,但我在某處讀到它是一種很好的形式。
您問題的本質是如何通過呼叫from
\
用正斜杠(ie)替換反斜杠(ie)。為此,您必須對反斜杠進行雙重轉義,因為該字元串將被處理兩次:一次通過呼叫 ,然後第二次通過呼叫. 這應該為您提供以下資訊:/``sed``find``find``sed
find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/cd c:\\\\project\\\\data\\\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod" \;
更詳細的解釋如下。
首先,讓我們為您的問題設置一個稍微簡單的範例:
# Create a target directory mkdir -p /tmp/dir1/mod/dir2 # Create a text file containing a backslash echo '\' > /tmp/dir1/mod/dir2/file.dct
現在讓我們嘗試使用
find
並sed
用正斜杠替換該反斜杠:find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\/\//' $(basename {})" \;
這會產生以下錯誤:
sed: -e expression #1, char 7: unterminated `s' command
那是因為
sed
正在執行的命令是這樣的:sed -e 's/\/\//' ./file.dct
您可以通過直接執行此命令來驗證您是否收到相同的錯誤,例如:
sed -e 's/\/\//' /tmp/dir1/mod/dir2/file.dct
您還可以通過
echo
在find
命令中執行來檢查這一點,例如:find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir echo "sed -e 's/\\/\//' $(basename {})" \;
為了修復命令,我們對反斜杠進行雙重轉義:
find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\\\/\//' $(basename {})" \;
這會產生所需的結果:
/