Так что после проверки я не смог найти опцию в diff
для вывода только различий в именах файлов, поэтому мы просто поработаем с тем, что выводит diff.
Если diff
находит файлы, которые отличаются, вывод будет примерно таким:
Files old/file and new/file differ
Поскольку ваш bash-скрипт будет переименовывать измененный файл из старого каталога, мы хотим извлечь old/file
из этого вывода. Давайте начнем с отображения только таких строк, как Files...differ
(как могут быть получены другие строки):
diff -rq old/ new/ | grep "^Files.*differ$"
Теперь вы получите только те строки, которые были показаны ранее. Следующим шагом является получение имени файла. Вы можете сделать это с помощью awk
, добавив что-то вроде awk '{print $2}'
в качестве другого канала, но если само имя файла содержит пробелы, awk разделит его на две отдельные строки. Вместо этого мы будем использовать sed:
diff -rq old/ new/ | grep "^Files.*differ$" | sed 's/^Files \(.*\) and .* differ$/\1/'
Теперь это создаст список файлов, которые были изменены в старом каталоге. Используя простой цикл for, вы можете теперь переименовать каждый из файлов:
for old_file in `diff -rq old/ new/ | grep "^Files.*differ$" | sed 's/^Files \(.*\) and .* differ$/\1/'`
do
mv $old_file $old_file.old
done
И это все!
edit: на самом деле, это еще не все. Этот цикл все еще не работает на файлах с пробелами, поэтому давайте немного с этим справимся. for
по умолчанию попытается создать список, разделенный пробелом. Давайте изменим это, чтобы использовать вместо этого новые строки:
OLD_IFS=$IFS
# The extra space after is crucial
IFS=\
for old_file in `diff -rq old/ new/ | grep "^Files.*differ$" | sed 's/^Files \(.*\) and .* differ$/\1/'`
do
mv $old_file $old_file.old
done
IFS=$OLD_IFS
Это временно заменяет разделитель по умолчанию в bash ($IFS
) на новую строку и возвращает его после завершения цикла, чтобы не разбивать пробел.