Сравните имена файлов в двух каталогах

#linux #bash

#linux #bash

Вопрос:

Мне нужно создать скрипт bash, который сравнивает содержимое по именам файлов в двух каталогах, например, «First_Directory» содержит файл с именем «123456», поэтому «Second_Directory» также должен содержать «_file_123456.png».
Если «Second_Directory» не содержит точного номера в имени файла из «First_Directory», скопируйте файл «dummy.png» из «Third_Directory» в «Second_Directory» и переименуйте его в соответствии с примером: «_file_ [First_Directory_File_Name].png»

Путь:
/path/to/directory/First_Directory/Second_Directory/
/home/имя пользователя/Third_Directory/dummy.png

Содержимое First_Directory:
123456
789012
345678

Содержимое второго каталога:
_file_123456.png
_file_789012.png
_file_345678.png

 DIR1=/path/to/directory/First_Directory/
DIR2=/path/to/directory/First_Directory/Second_Directory/
PNG=/home/username/Third_Directory/dummy.png

DIFF=$(diff <(find $DIR1 -maxdepth 1 -type f -name "*" -printf '%fn') <(find $DIR2 -type f -name '_file_*.png' -printf '%fn'))

if [ "$DIFF" ];
then
   cp $PNG $DIR2
fi
  

Мой скрипт отображает только разницу между этими двумя каталогами. Я не смог найти решение о том, как сравнивать только определенную часть имени файла. Он также должен скопировать и переименовать файл в «Second_Directory», как я упоминал в описании.

Комментарии:

1. Что должно произойти, если файл существует во втором каталоге без соответствующего файла в первом каталоге?

2. @choroba Привет, не следует проверять это условие, поскольку в моем случае может отсутствовать соответствующий файл только в First_directory.

Ответ №1:

Цикл по первому каталогу был бы здесь правильным решением. Для вашего обновленного требования вы можете сначала найти базовые каталоги и зациклить их.

 for DIR1 in `find . -name First_Directory_*`
do
   DIR2="$DIR1"/Second_Directory
   PNG=/path/to/dummy.png
   for file in "$DIR1"/*
   do
     if [ -f "$file" ]; then
        dir2_file="$DIR2"/_file_${file##*/}.png
        if [ ! -f "$dir2_file" ]; then
           cp "$PNG" "$dir2_file"
        fi
     fi
   done
done
  

Комментарии:

1. Большое вам спасибо за помощь, но у меня есть еще один вопрос. Допустим, у меня есть путь к каталогу, подобный этому: «/path/to/directory/Project_1/Test_1/First_Directory/Second_Directory /». В моем случае «/ path / to /directory /» и «/ Second_Directory /» всегда будут постоянными, но имя для этих трех каталогов: «/Project_1 /Test_1 /First_Directory /» будет отличаться, поскольку в моем случае существует много проектов. Можно ли проверить «First_Directory», даже если у него будут разные имена?

2. Я не совсем понимаю, что вы имеете в виду. Вы правильно назначаете DIR1 и DIR2? У вас есть разные пары каталогов, к которым вы хотите применить одну и ту же операцию? Пример использования поможет уточнить больше.

3. Пример структуры каталогов: ссылка на изображение . «/path/ to/directory/» всегда останется неизменным, но следующие три имени каталога будут совершенно случайными, за исключением «Second_Directory». Идея состоит в том, чтобы пройти три уровня вглубь (начиная с «/ path / to /directory /») в каждый из этих каталогов и выполнить скрипт.

4. Если я использую цикл for, который вызывает вашу функцию проверки файлов, будет ли это правильным решением? function() { ... } for dir in /path/to/directory/*/*/*; do (cd "$dir" amp;amp; function); done

5. Я не думаю, что вы можете подойти к этому таким образом. Вам нужен точный список папок, и вам нужно перебрать эти папки и вызвать функцию.

Ответ №2:

Вы можете перебрать все файлы в первом каталоге с помощью цикла for:

 #! /bin/bash
dir1=...
dir2=...
dummy=...    

for file in "$dir1"/* ; do
    target=$dir2/_file_${file##*/}.png
    [[ -f $target ]] || cp "$dummy" "$target"
done
  

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

Комментарии:

1. Да, исходные файлы находятся в First_Directory , но без префикса или суффикса. Не уверен *.png , что будет соответствовать чему-нибудь полезному.