Мне нужно создать сценарий bash, который сравнивает содержимое по именам файлов в двух каталогах, например, «First_Directory» содержит файл с именем "123456", поэтому «Second_Directory» также должен содержать "_file_123456.png".
Если «Second_Directory» не содержит точного номера в имени файла из «First_Directory», то скопируйте файл «dummy.png» из «Third_Directory» во «Second_Directory» и переименуйте его в соответствии с примером: "_file_[Первый_Каталог_Имя_Файла].png"
Путь:
/путь/к/каталогу/Первый_Каталог/Второй_Каталог/
/home/username/Third_Directory/dummy.png
Содержимое First_Directory:
123456
789012
345678
Содержимое Second_Directory:
_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 '%f\n') <(find $DIR2 -type f -name '_file_*.png' -printf '%f\n'))
if [ "$DIFF" ];
then
cp $PNG $DIR2
fi
Мой скрипт отображает только разницу между этими двумя каталогами. Я не смог найти решение, как сравнивать только определенную часть имени файла. Он также должен скопировать и переименовать файл в «Second_Directory», как я упоминал в описании.
@choroba Здравствуйте, это условие не должно проверяться, так как в моем случае соответствующий файл может отсутствовать только в First_directory.
Вы можете перебрать все файлы в первом каталоге с помощью цикла for:
#! /bin/bash
dir1=...
dir2=...
dummy=...
for file in "$dir1"/* ; do
target=$dir2/_file_${file##*/}.png
[[ -f $target ]] || cp "$dummy" "$target"
done
Не используйте имена переменных в верхнем регистре для несистемных переменных, чтобы предотвратить конфликты.
Да, исходные файлы находятся в Первый_Каталог, но без префикса или суффикса. Не уверен, что *.png
будет соответствовать чему-то полезному.
Здесь правильным решением будет цикл по первому каталогу. Для вашего обновленного требования вы можете сначала найти базовые каталоги и зациклить их.
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
Большое спасибо за помощь, но у меня есть еще один вопрос. Допустим, у меня есть такой путь к каталогу: "/path/to/directory/Project_1/Test_1/First_Directory/Second_Directory/". В моем случае "/path/to/directory/" и "/Second_Directory/" всегда будут постоянными, но имя для этих трех каталогов: "/Project_1/Test_1/First_Directory/" будет отличаться, так как в моем случае проектов много . Можно ли проверить «First_Directory», даже если у него будут разные имена?
Я не совсем понимаю, что вы имеете в виду. Вы правильно назначаете DIR1 и DIR2? У вас есть разные пары каталогов, к которым вы хотите применить одну и ту же операцию? Пример варианта использования поможет уточнить больше.
Пример структуры каталога: Ссылка на изображение. «/path/to/directory/» всегда останется прежним, но следующие три имени каталога будут совершенно случайными, за исключением «Second_Directory». Идея состоит в том, чтобы перейти на три уровня вглубь (начиная с «/path/to/directory/») в каждый из этих каталогов и выполнить скрипт.
Если я использую цикл for, который вызывает вашу функцию проверки файлов, будет ли это правильным решением? function() { ... } for dir in /path/to/directory/*/*/*; do (cd "$dir" && function); done
Я не думаю, что вы можете подойти к этому таким образом. Вам нужен точный список папок, и вам нужно перебрать эти папки и вызвать функцию.
Если вы уверены, что имя будет начинаться с First_Directory_*, вы можете использовать это, чтобы получить список каталогов для цикла.
Проверьте обновленный ответ. Это грубое решение для вашего требования.
Спасибо за помощь! Я отмечу это как ответ и собираюсь найти наиболее подходящий вариант для моей ситуации на основе предоставленных решений.
Что должно произойти, если файл существует во Second_Directory без соответствующего файла в First_Directory?