Соответствие файлов в каталоге и проверка

У меня есть файлы в каталоге (/ home / user / example), которые мне нужно проверить и сопоставить. Каждый файл имеет файл управления и данных. Я хочу проверить, есть ли для каждого файла соответствующий файл другого. Например, если example.ctl имеет соответствие с example.out или example.out имеет соответствующий файл с example.ctl.

Я написал вложенный цикл for и множество операторов if else. Но это казалось слишком сложным для такой базовой проверки, как эта. Я хотел посмотреть, есть ли у кого-нибудь лучшее решение.

Примеры файлов в каталоге:

example.ctl example.out example_1.ctl example_1.out example_2.ctl example_2.out 

Первый вариант

Он просматривает все имена файлов и проверяет каждый файл, имеет ли он пару или нет, и печатает соответствующее сообщение.

 for i in *; do base=${i%.*} if [ -e "${base}.out" -a -e "${base}.ctl" ]; then printf 'file "%s" has a pair\n' "$i" else printf 'file "%s" has not a pair\n' "$i" fi done 

Второй вариант

Он перебирает .ctl файлы .ctl и проверяет, есть ли в текущем файле .ctl пара – файл .out . Таким образом, он печатает только парные файлы, исключая остальные – непарные файлы.

 for i in *.ctl; do base=${i%.*} if [ -e "${base}.out" ]; then printf 'file "%s" has a pair "%s"\n' "$i" "${base}.out" fi done 
 comm <(basename -a -s.ctl *.ctl | sort) <(basename -a -s.out *.out | sort) 

Смотрите comm(1) , особенно флаги -12 будут перечислять только файлы с обоими суффиксами.

Вы пытаетесь обнаружить отсутствующие файлы .ctl и .out, поэтому вам нужно проверить оба пути. Простой способ сделать это (если имена ваших файлов не содержат специальных символов, включая пробелы и содержат только одну точку), это

  1. найти все файлы с помощью find . -type f find . -type f ,
  2. удалить расширение каждого из них с помощью cut --delimiter=. --fields=1 cut --delimiter=. --fields=1 ,
  3. sort --unique для удаления дубликатов,
  4. перебирайте их с while read name , и, наконец,
  5. проверьте, существует ли каждый из файлов с помощью [[ -e "${name}.ctl" ]] || echo "${name}.ctl" >&2 [[ -e "${name}.ctl" ]] || echo "${name}.ctl" >&2 и то же самое для .out.

Вы можете циклически перемещаться по файлам и получать ожидаемые имена файлов для файлов вывода и управления. Сделав это, вы можете проверить, что оба существуют:

 for item in *.out *.ctl do base="${item%???}" out="$base.out" ctl="$base.ctl" [ -f "$out" -a ! -f "$ctl" ] && echo "$out is missing $ctl" >&2 [ -f "$ctl" -a ! -f "$out" ] && echo "$ctl is missing $out" >&2 done