bash从绝对路径获取相对路径



这行获得绝对路径,我使用output将其传递给rsync,但rsync需要相对路径

find /www-data/ -type f -exec sh -c 'if ! lsof `readlink -f {}` > /dev/null; then echo `realpath {}`; fi' ; | tr 'n' '' 

不知道如何从上面的输出输入realpath -relative-to

完整代码:

cd /www-data
find ./ -type f -exec sh -c 'if ! lsof `readlink -f {}` > /dev/null; then echo `realpath {}`; fi' ; | tr 'n' '' | rsync -avz --from0 --files-from=- ./ /data/map/uploads/ --dry-run

使用tr 'n' '00'从根本上是被打破的。你想要推入以空结尾的字符串的原因是为了消除作为文件名一部分的换行和那些不是的换行之间的歧义;但是如果你替换了所有的换行符,你并没有消除任何歧义。也可参见https://mywiki.wooledge.org/BashFAQ/020

类似地,echo `command`只是对echo的无用使用,除非您特别希望shell在command的输出中压缩空白并扩展通配符。

如果我可以稍微猜一下你到底想问什么,试试

find ./ -type f -exec sh -c 'for f; do
lsof "$(readlink -f "$f")" > /dev/null ||
printf "%s" "$(realpath --relative-to /var/www-data "$f")"
done' _ {} + |
rsync -avz --from0 --files-from=- ./ /data/mapis/clientuploads/ --dry-run

关键的变化是让find将文件名作为参数传递给sh -c '...',而不是试图在字符串中间直接替换{},这可能需要或不需要引号。

在末尾使用-exec ... {} ++应该会在一定程度上提高效率,而在嵌入的sh脚本中添加for循环的代价非常小。