在bash中有效地重新读取(或以其他方式重用)输入文件中的内容

时间:2016-10-05 03:11:02

标签: bash

我想通过以下代码将命令应用于目录target_dir中的文件。

for t_file in $(find 'target_dir' -maxdepth 1 -type f);
do
  exec {fd}<'command_list.txt'
  while read -u "${fd}" eval_command
  do
    eval "${eval_command}"
  done
  exec {fd}>&-
done

command_list.txt的一个例子是

# command_list.txt
cat "${t_file}"

程序为每个文件加载command_file.txt但是 我希望如果我可以将文件指针移回文件的第一行而不需要在迭代之间关闭并重新打开它,效率会更高。

exec {fd}<'command_list.txt'

for t_file in $(find 'target_dir' -maxdepth 1 -type f);
do

  (move cursor of read to the first line of 'command_list.txt')

  while read -u "${fd}" eval_command
  do
    eval "${eval_command}"
  done

done

exec {fd}>&-

正在寻找一个文件指针回到文件的开头,而无需在bash中重新打开它吗?

2 个答案:

答案 0 :(得分:2)

回答文字问题:你可以在bash中寻找一个文件描述符,只有一个可加载的模块(插件)添加一个新的内置,或者通过旋转一个外部程序(继承你的文件描述符)并询问进行搜索操作(this answer中给出的方法)。但是,启动外部程序的成本更大比仅关闭和重新打开文件的成本更高,因此在这种情况下,这不是真正有意义的方法。

如果要存储命令列表,只需执行此操作 - 将其存储为数组。如果通过&#34;移动光标&#34;你指的是在输入文件中寻找,bash并没有在默认的内置集中提供搜索原语 - 但无论如何都不需要它。

# read command_list.txt only once, storing its contents in an array
readarray -t eval_commands < command_list.txt

while IFS= read -r -d '' t_file <&3; do          # iterate over filenames from find
  for eval_command in "${eval_commands[@]}"; do  # iterate over your array
    eval "$eval_command"
  done
done 3< <(find target_dir -maxdepth 1 -type f -print0)

顺便说一句 - 如果你要将你的文件名作为参数传递给命令而不是替换它,你想要这样做:

# put the filename expansion in *single quotes*
eval "$eval_command "'"$t_file"'

......或如下:

# generate a safe version of the filename
printf -v t_file_q '%q' "$t_file"

# ...and use that safe version instead of the original
eval "$eval_command $t_file_q"

如果有人eval "$eval_command $t_file" - 不遵循这些预防措施之一 - 使用touch $'target_dir/hello world $(rm -rf $HOME)'创建的文件将是非常糟糕的消息。

答案 1 :(得分:0)

find 'target_dir' -maxdepth 1 -type f -exec cat {} \;

这会捕获目标目录1文件夹中的每个文件。