Bash 使用perl将软链接/symlink更改为静态文件就地替换
发出以下命令:Bash 使用perl将软链接/symlink更改为静态文件就地替换,bash,git,perl,Bash,Git,Perl,发出以下命令: git ls-files | xargs perl -i -pe 's/SEARCHTERM/REPLACETERM/g' 所有输出到perl(来自git ls文件)的符号链接现在都是目标文件的副本 我有两个问题: 1) 我想我模糊地理解了为什么会发生这种事,但只是模糊地理解。有人能详细解释一下吗?并提出避免这种情况的最佳机制?预期的行为是,符号链接目标将是读和写的目标,而不仅仅是读 2) 在本地git分支上进行搜索和替换是否有更好的通用方法 可能值得注意的是,我的bash非常
git ls-files | xargs perl -i -pe 's/SEARCHTERM/REPLACETERM/g'
所有输出到perl(来自git ls文件)的符号链接现在都是目标文件的副本
我有两个问题:
1) 我想我模糊地理解了为什么会发生这种事,但只是模糊地理解。有人能详细解释一下吗?并提出避免这种情况的最佳机制?预期的行为是,符号链接目标将是读和写的目标,而不仅仅是读
2) 在本地git分支上进行搜索和替换是否有更好的通用方法
可能值得注意的是,我的bash非常初级,当我希望确保处理文件内容而不是文件列表时,
xargs
只是我的默认goto。除此之外,不得使用。如果您不反对使用sed,请尝试一下:
git ls-files | xargs -I{} -P4 sed --follow-symlinks -i'' 's/SEARCHTERM/REPLACETERM/g' {}
上面写着
请注意,由于-i
在创建同名新文件之前会重命名或删除原始文件,因此不会保留Unix样式的软链接和硬链接
因此,使用-i
无法做到这一点
这里是Perl的另一种方法(正如标记的一样——即使有一个干净的解决方案使用sed
)
我使用文件a.txt
、b.txt
、它们的符号链接(ln-sa.txt ln_a.txt
等)和c.txt
(任何内容都可以用于此测试),并在文件中列出链接和c.txt
的名称
ln_a.txt ln_b.txt c.txt # file "input_list.txt"
这将更改目标的内容,并保留链接。它也适用于常规文件
临时输出文件名(filename\u tmp.$
)可以使用file::Temp
,或者更确切地说是使用,因为该模块已经被使用
为便于携带,可能应将更改为从移动到
as used检查每个输入文件的文件是否已用尽,此时输出文件将重命名为输入文件或其目标。-l
是一个测试手头上的文件是否是符号链接的函数,如果是,则解析该链接
由于输入文件或目标已被读取和处理,因此此时可以安全地对其进行重命名
名字是什么
当前处理的文件的名称,并且是该文件的文件句柄
显式的
close ARGV
重置行计数器,这样我们就可以在每个新输入文件的开头打开临时输出,方法是根据1
测试行号计数器。对此,我最初的解决方案是让符号链接被阻塞,然后运行:
git status --porcelain | awk '{if ($1 == "T"){print $2}}' | xargs git checkout
这对于各种工具来说非常有用,如果符号链接碰巧是偶然的,并且与搜索不相关,那么它们可能会破坏符号链接
这里的链接有一些有趣的想法:
我认为zdim的答案是其中一个的最佳实现。不过有点毛茸茸的
该链接的另一个答案是使用海绵
,它可以工作,但会创建一个非常复杂的xargs管道。我认为,它还需要使用xargs-n1
,这是在大型文件系统上运行perl的一种极其缓慢的方式。所以这是不可能的
Rafael的答案(仅使用sed)可能是……解决这个问题的最明智的方法:)另一个Perl选项:
git ls-files | xargs perl -MPath::Tiny -Mutf8 -E'
path($_)->realpath->edit_lines_utf8(sub { s/SEARCHTERM/REPLACETERM/g })
for @ARGV'
或者不使用xargs,只需从STDIN读取文件名:
git ls-files | perl -MPath::Tiny -Mutf8 -E'
path($_)->realpath->edit_lines_utf8(sub { s/SEARCHTERM/REPLACETERM/g })
for map { chomp; $_ } readline'
realpath
确保您始终使用symlink目标,并且本质上是-i
选项的一个Path::微小实现。使用edit_lines\u utf8
和-Mutf8
意味着您的源代码(搜索和替换术语)和文件内容将在运行搜索/替换时从UTF-8解码,这通常很有用(但如果您的文件不是UTF-8编码的,请删除-Mutf8
并使用编辑_lines
)。您还可以根据筛选出非文本文件,方法是在for
之后添加grep{-T}
作为奖励,edit_line
将始终输出到新文件,然后将其重命名为原始文件,这比删除原始文件更安全
注意:Path::Tiny将根据您当前的umask设置其编辑的所有文件的权限,而不是现有权限;我打开查看它是否被认为是一个bug。您只需要
git ls-files | xargs readlink -e | xargs perl -i -pe'...'
您还可以在Perl中扩展链接
git ls-files | xargs perl -i -pe'BEGIN { @ARGV = map readlink($_) // $_, @ARGV } ...'
恐怕是同样的结果。(虽然我不得不删除
”
fwiw)是的,这很有效。谢谢另外,“关注符号链接”是一个有用的谷歌搜索,它让我找到了这个:@zzxyz,这真是个漂亮的老板!Def将阅读更多关于moreutils的信息。谢谢。我希望我永远不必使用它,但如果我使用它,它将是无价的。@zzxyz是的,很好有sed
功能和它的答案:)。这只是一个简单的-i
实现,它尊重符号链接。它包含了一堆花絮,我希望这些花絮通常是有用的。
git ls-files | xargs perl -i -pe'BEGIN { @ARGV = map readlink($_) // $_, @ARGV } ...'