Сценарий оболочки для проверки имени файла с двумя расширениями и, если файл с обоими расширениями присутствует, вызывает сценарий, в противном случае он должен завершиться ошибкой

Я буду использовать опцию --to-commandдля запуска печати всех извлеченных файлов

аргумент представляет собой команду, которая будет использовать переменную env TAR _FILENAME для получения имени файла и получит файл наSTDIN

Таким образом, вы должны прочитать STDINи создать извлеченный файл, вы можете распечатать на STDOUTсозданный вами файл

tar -xzf../ARCH.tgz --keep-newer-files \
   --to-command="sh -c $(printf '%q' \
  'mkdir -p "$(dirname "$TAR_FILENAME")";dd of="$TAR_FILENAME" >/dev/null 2>&1;echo "#EXTRACTED#$TAR_FILENAME" ')" > output_tar.txt

и в output_tar.txtу вас будет строка для каждого извлеченного файла.

см.https://www.gnu.org/software/tar/manual/html_node/Writing-to-an-External-Program.html

0
04.11.2020, 07:02
2 ответа
#!/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

Вопрос был не очень ясен, поэтому я предположил, что вы хотите проверить все файлы в определенном каталоге на наличие одного из этих двух расширений.

1
18.03.2021, 22:52

Мне непонятно, что именно вы хотите проверить. Вот несколько способов решить вашу проблему в оболочке zsh:

.
#! /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}"сохраняет пустые элементы (, например, когда есть файл с именем .txtили.ctl).
  • ${A:|B}вычитание из двух массивов (элементов A, которых нет вB).
  • $#array:количество элементов в массиве.
  • (( arithmetic expression ))вычисляет арифметическое выражение и возвращает true , если результат отличен от 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заменены глобальными опциями nullglobи dotglob.
  • :tс шаблоном "${array[@]##*/}"-удаление оператора ksh
  • :rс шаблоном "${array[@]%*/}"-удаление оператора ksh
  • объединение и вычитание массива выполняется с использованием sort+ commдля записей с разделителями NUL -и в локали C (NUL является единственным байтом, который не может быть найден в имени файла (или в переменных bash, как это бывает )).
1
18.03.2021, 22:52

Теги

Похожие вопросы