有没有办法让 perl -i 不破坏符号链接?

有没有办法让 perl -i 不破坏符号链接?

我的一个朋友指出,如果你这样做:

perl -pi.bak -e 's/foo/bar/' somefile

当“somefile”实际上是一个符号链接时,perl 就会按照文档所说的那样执行:

它通过重命名输入文件、按原始名称打开输出文件并选择该输出文件作为 print() 语句的默认文件来实现此目的。扩展名(如果提供)用于修改旧文件的名称以制作备份副本 [...]

这会产生一个新的符号链接“somefile.bak”,指向未更改的真实文件,以及一个新的、已更改的常规文件“somefile”,其中包含更改。

在许多情况下,遵循符号链接将是所需的行为(即使它使 .bak 文件的正确位置不明确)。除了测试包装器中的符号链接并适当处理这种情况之外,是否有一种简单的方法可以做到这一点?

sed做同样的事情,为了它的价值。)

答案1

我想知道是否是小sponge通用实用程序(“吸收标准输入并写入文件”)更多实用程序在这种情况下以及它是否遵循符号链接将会有所帮助。

作者描述 sponge像这样:

它解决了使用 Unix 工具就地编辑文件的问题,即如果您只是将输出重定向到您要编辑的文件,则重定向会在管道中的第一个命令之前生效(破坏文件的内容)抽出时间来读取文件。诸如sed -i和 之类的开关可以perl -i解决此问题,但并非您可能想要在管道中使用的每个命令都有这样的选项,并且无论如何您都不能在多命令管道中使用该方法。

我通常使用海绵有点像这样:

sed '...' file | grep '...' | sponge file

答案2

如果您知道符号链接这一事实somefile,则可以使用以下命令显式提供文件的完整路径:

perl -pi.bak -e 's/foo/bar/' $(readlink somefile)

这样,原始符号链接将保持不变,因为替换现在是直接使用原始文件完成的。

答案3

如果您正在处理单个文件,该命令将如下所示:

perl -i -pe'...' -- "$qfn"

那么解决方案如下:

perl -i -pe'...' -- "$( readlink -e -- "$qfn" )"

这可以处理符号链接和非符号链接。


如果您正在处理任意大量的文件,该命令将如下所示:

... | xargs -r perl -i -pe'...' --

那么解决方案如下:

... | xargs -r readlink -ze -- | xargs -r0 perl -i -pe'...' --

这可以处理符号链接和非符号链接。


警告 readlink不是标准命令,因此它的存在、参数和功能因系统而异,因此请务必检查您的文档。例如,有些实现有-f(您也可以在此处使用),但没有-e,有些则两者都没有。busyboxreadlink -f行为类似于 GNU readlink -e。有些系统有一个realpath命令,而不是readlink通常表现得像 GNU readlink -f

请注意,使用 GNU 时readlink -e,无法解析为现有文件的符号链接将被静默删除。

相关内容