#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
, что будет соответствовать чему-нибудь полезному.