使用 shell 脚本列出以 .in 结尾的任何文件以及相应的 .out

使用 shell 脚本列出以 .in 结尾的任何文件以及相应的 .out

我有一个充满以不同扩展名结尾的文件的目录,如何仅列出/选择以.in和 对应的.out共享相同基名的文件?

例如

file1.txt
file1.in
file2.in
file3.in
file2.out
file3.out

我想从这些文件中选择的是:

file2.in
file2.out
file3.in
file3.out

答案1

由于要.in与 配对.out,因此仅循环*.in并检查是否有相应的.out文件,如果有,则打印出两者:

for f in *.in; do
  if [[ -f ${f%.in}.out ]]; then
    echo $f
    echo ${f%.in}.out
  fi
done

答案2

首先匹配所有文件,并检查 .out 文件是否存在,然后打印名称:

for x in *; do
   if [[ "$x" =~ ^(.*)\.in ]] && [[ -f ${BASH_REMATCH[1]}.out ]];then 
      echo -n "$x ${x%%.in}.out "; 
   fi
done
echo

答案3

使用 zsh:

has_out() [[ -e $REPLY:r.out ]]
ls -ld -- *.in(+has_out)

答案4

您可以列出所有这些文件,删除扩展名,过滤重复项并打印它们:

$ ls | grep '\(\.in\|.out\)$' | sed 's/....$//' \
     | sort | uniq -c | grep '^[\t ]*2' | sed 's/^[\t ]\+2 //'

优点:

  • 不需要bash
  • 仅执行一项昂贵的操作 - 目录列表 - 即不需要统计数据(2)每个文件(如[[ -f ... ]]

如果ls已经按字母顺序排序其输出,sort则可以从管道中删除该命令。我不知道 POSIX 是否指定了ls.

.in该管道会打印带有扩展名的文件的所有基本名称.out

如果您随后需要相应文件的列表,则必须在列表中添加先前过滤的扩展名的后缀。例如这样:

$ ls | grep '\(\.in\|.out\)$' | sed 's/....$//' \
     | sort | uniq -c | grep '^[\t ]*2' \
     | sed -e 's/^[\t ]\+2 //' -e 's/$/.in/ ; p; s/in$/out/'

相关内容