用于检查具有两个扩展名的文件名的 Shell 脚本,如果存在两个扩展名的文件,则调用脚本,否则会失败

用于检查具有两个扩展名的文件名的 Shell 脚本,如果存在两个扩展名的文件,则调用脚本,否则会失败

我需要检查目录中具有两个扩展名(.txt 和 .ctl)的文件,如果文件存在同时具有两个扩展名,则调用脚本。如果不是,工作就会失败。我尝试了一些方法,但它没有按预期工作。谁能帮帮我吗。

答案1

#!/bin/bash

# Assuming the directory is passed to us as an argument...
DIR="$1"
SCRIPT=/path/to/the/other/script.sh

COUNT=0
for i in "$DIR"/*.txt "$DIR"/*.ctl ;do
  if [ -f "$i" ] ;then # this is a regular file
    ((COUNT++))
    "$SCRIPT" "$i"
  fi
done

if [ $COUNT -eq 0 ] ;then
   exit 1 # No .txt or .ctl files were found.
fi

问题不是很清楚,所以我假设您想要检查某个目录中的所有文件是否有这两个扩展名。

答案2

我不清楚你到底想检查什么。这里为您提供一些解决zshshell 中问题的途径:

#! /bin/zsh -

for dir do
  txt=($dir/*.txt(ND:t:r))
  ctl=($dir/*.ctl(ND:t:r))
  both=("${(@)txt:*ctl}")
  txt_but_not_ctl=("${(@)txt:|ctl}")
  ctl_but_not_txt=("${(@)ctl:|txt}")

  print -r -- "$dir has $#txt file${txt[2]+s} with a .txt extension"
  print -r -- "$dir has $#ctl file${ctl[2]+s} with a .ctl extension"
  print -r -- "$#both .txt file${both[2]+s} in $dir have matching files with the same root name and a .ctl extension"
  print -r -- "$dir has $#txt_but_not_ctl .txt file${txt_but_not_ctl[2]+s} without a corresponding .ctl file"
  print -r -- "$dir has $#ctl_but_not_txt .ctl file${ctl_but_not_txt[2]+s} without a corresponding .txt file"

  (($#both && $#txt_but_not_ctl == 0 && $#ctl_but_not_txt == 0)) &&
    print -r -- "all the .txt files in $dir have a corresponding .ctl file and vis versa"
done

这里感兴趣的关键结构是:

  • files=(*(DN)):将与模式匹配的文件列表分配给数组变量。D包含隐藏列表,N允许空列表 ( nullglob)。
  • :t:r,取(删除目录部分),以及删除扩展名。
  • ${A:*B}两个数组的交集。"${(@)A:*B}"保留空元素(例如当有一个名为.txtor 的文件时.ctl)。
  • ${A:|B}两个数组相减(A其中的元素不在 中B)。
  • $#array:数组中元素的数量。
  • (( arithmetic expression ))计算算术表达式并返回真的如果结果不是 0。

如果在最近的基于 GNU 的系统上,您可以执行以下操作bash(尽管更加笨拙、痛苦且效率较低):

#! /bin/bash -
shopt -s nullglob dotglob

printz() {
  (($# == 0)) || printf '%s\0' "$@"
}

for dir do
  txt=("$dir"/*.txt)
  txt=("${txt[@]##*/}")
  txt=("${txt[@]%.*}")
  ctl=("$dir"/*.ctl)
  ctl=("${ctl[@]##*/}")
  ctl=("${ctl[@]%.*}")

  readarray -td '' both < <(
    LC_ALL=C comm -z12 <(printz "${txt[@]}" | LC_ALL=C sort -z) \
                       <(printz "${ctl[@]}" | LC_ALL=C sort -z))
  readarray -td '' txt_but_not_ctl < <(
    LC_ALL=C comm -z13 <(printz "${txt[@]}" | LC_ALL=C sort -z) \
                       <(printz "${ctl[@]}" | LC_ALL=C sort -z))
  readarray -td '' ctl_but_not_txt < <(
    LC_ALL=C comm -z23 <(printz "${txt[@]}" | LC_ALL=C sort -z) \
                       <(printz "${ctl[@]}" | LC_ALL=C sort -z))

  printf '%s\n' "$dir has ${#txt[@]} file${txt[2]+s} with a .txt extension"
  printf '%s\n' "$dir has ${#ctl[@]} file${ctl[2]+s} with a .ctl extension"
  printf '%s\n' "${#both[@]} .txt file${both[2]+s} in $dir have matching files with the same root name and a .ctl extension"
  printf '%s\n' "$dir has ${#txt_but_not_ctl[@]} .txt file${txt_but_not_ctl[2]+s} without a corresponding .ctl file"
  printf '%s\n' "$dir has ${#ctl_but_not_txt[@]} .ctl file${ctl_but_not_txt[2]+s} without a corresponding .txt file"

  ((${#both[@]} && ${#txt_but_not_ctl[@]} == 0 && ${#ctl_but_not_txt[@]} == 0)) &&
    printf '%s\n' "all the .txt files in $dir have a corresponding .ctl file and vis versa"
done

在哪里:

  • N并被D替换为全局nullglobdotglob选项。
  • :t使用"${array[@]##*/}"模式剥离 ksh 运算符
  • :r使用"${array[@]%*/}"模式剥离 ksh 运算符
  • 数组并集和减法是在 NUL 分隔记录和 C 语言环境中使用sort+执行的comm(NUL 是在文件名中(或在 bash 变量中)找不到的唯一字节)。

相关内容