我想更改不同子目录中某些文件的一行。这些文件将始终具有扩展名.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
可能有点矫枉过正,但我在某处读到这是一种很好的形式。
答案1
您问题的本质是如何通过调用from 将反斜杠(即\
)替换为正斜杠(即/
)。为此,您必须对反斜杠进行双转义,因为该字符串将被处理两次:一次通过调用 进行处理,第二次通过调用 进行处理。这应该给你以下信息: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 {})" \;
这会产生所需的结果:
/