在bash脚本中对每个文件使用exec

时间:2015-02-27 11:20:41

标签: arrays linux bash shell sed

我尝试为作业编写基本find命令(不使用find)。现在我有一些我想要exec的文件。语法如下所示:

-exec /bin/mv {} ~/.TRASH

我有一个名为current的数组,它包含所有文件。我的数组只保存/bin/mv{}~/.TRASH(因为我将-exec移出)并且位于名为arguments的数组中。

我需要它,以便每个文件都传递到{}并在其上调用exec。

我认为我应该使用sed替换{}这样的内容(在for循环中):

for i in "${current[@]}"; do
    sed "s@$i@{}" 
    #exec stuff?
done

我如何执行其他参数?

2 个答案:

答案 0 :(得分:1)

你可以这样:

cmd='-exec /bin/mv {} ~/.TRASH'    
current=(test1.txt test2.txt)

for f in "${current[@]}"; do 
   eval $(sed "s/{}/$f/;s/-exec //" <<< "$cmd")
done

请谨慎使用eval命令,因为如果输入来自不受信任的来源,它可能会产生令人讨厌的事情。


这是试图避免eval(感谢@gniourf_gniourf的评论):

current=( test1.txt test2.txt )
arguments=( "/bin/mv" "{}" ~/.TRASH )

for f in "${current[@]}"; do
   "${arguments[@]/\{\}/$f}"
done

答案 1 :(得分:1)

你很幸运,你的设计并不太糟糕,你的论点都在一个阵列中。

但你肯定不想使用eval

所以,如果我理解正确,你有一个文件数组:

current=( [0]='/path/to/file'1 [1]='/path/to/file2' ... )

和一系列参数:

arguments=( [0]='/bin/mv' [1]='{}' [2]='/home/alex/.TRASH' )

请注意,这里没有波浪号,因为Bash已经扩展了它。

执行您想要的任务:

for i in "${current[@]}"; do
    ( "${arguments[@]//'{}'/"$i"}" )
done

观察报价。

这将通过{}的扩展(即文件名 1 )替换arguments字段中$i的所有出现次数,并执行这种扩张。请注意,数组的每个字段将扩展为一个参数(由于引号),因此所有这些对于空格,glob字符等都非常安全。这是最安全和最正确的方法。使用eval的每个解决方案都有潜在的危险和破坏(除非使用某些特殊引用,例如printf '%q',但这会使该方法无用尴尬)。顺便说一下,使用sed也至少在两个方面被打破了。

请注意,我将扩展包含在子shell中,因此用户无法干扰您的脚本。如果没有这个,并且根据你的完整脚本的编写方式,很容易让你的脚本突然(恶意地)改变一些变量或者cd - 在其他地方。在子shell中运行你的参数,或者在一个单独的进程中运行你的参数(例如,单独的bash或sh实例 - 但这会增加额外的开销)是出于明显的安全原因而非常强制的!

请注意,使用您的脚本,用户可以直接访问所有Bash内置版本(这是一个巨大的专业版),与一些更标准的find版本 2 相比!


1 请注意POSIX clearly specifies that this behavior is implementation-defined

  

如果 utility_name 参数字符串包含两个字符&#34; {}&#34;,而不仅仅是两个字符&#34; {} &#34;,是实现定义的 find 是否替换这两个字符或使用字符串而不做更改。

在我们的例子中,我们选择用文件名替换所有出现的{}。这与例如GNU find的行为相同。来自man find

  

字符串{}被在命令参数中出现的任何位置处理的当前文件名替换,而不仅仅是在单独的参数中,就像在某些版本的find中一样。


2 POSIX also specifies that calling builtins is not defined

  

如果 utility_name 命名任何特殊的内置实用程序(请参阅Special Built-In Utilities),结果将是未定义的。

在你的情况下,它定义得很好!


我认为尝试实现(在纯粹的Bash中)一个find命令是一个很好的练习,应该教你很多...特别是如果你得到相关的反馈。我很乐意审核您的代码!