我有一个充满以不同扩展名结尾的文件的目录,如何仅列出/选择以.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/'