我正在尝试自动创建目录的符号链接,并在链接名称 (bar) 中替换原始名称的某个文本字符串 (foo)。目标目录的名称可能包含空格(例如“foo with whitespace”)。
这是一个最小的例子:
> ls -Q
"foo"
"foo with whitespace"
我正在尝试以下命令(使用 xargs 的 -p 选项在执行之前调试/检查结果):
find . -iname "*foo*" -print0 | xargs -0 -I '{}' -p ln -s {} `echo {} | sed -e s#foo#bar#g
我想要的结果是这样的:
ln -s 'foo with whitespace' 'bar with whitespace'
ln -s 'foo' 'bar'
但是字符串替换失败。实际输出如下所示:
ln -s './foo with whitespace' './foo with whitespace'?...
ln -s ./foo ./foo?...
如果我使用常量字符串而不是 {},则字符串替换将按预期工作:
find . -iname "*foo*" -print0 | xargs -0 -I '{}' -p ln -s {} `echo "foo" | sed -e s#foo#bar#g`
ln -s './foo with whitespace' bar?...
ln -s ./foo bar?...
我的错误是什么以及如何修复命令调用?
编辑:Tilman Schmidt 的解决方案奇迹般有效。
答案1
命令替换
`echo {} | sed -e s#foo#bar#g`
仅执行一次,前运行由find
和命令组成的管道。因此获取字符串作为输入,并且未找到,则将其原封不动地输出。
xargs
sed
{}
foo
然后shell 运行结果命令行
find . -iname "*foo*" -print0 | xargs -0 -I '{}' -p ln -s {} {}
因此,命令替换在这里不是合适的工具。尝试以下方法
find . -iname "*foo*" -print | while read f; do ln -s "$f" "${f//foo/bar}"; done
(未经测试)代替。请注意,如果您的文件名包含换行符,则此方法无效。