Вы можете использовать find
, чтобы найти все файлы в дереве каталогов, которые соответствуют (или не соответствуют) некоторым конкретным тестам, а затем что-то с ними сделать. Для этой конкретной проблемы вы можете использовать:
find -type f ! \( -iname '*.png' -o -iname '*.gif' -o -iname '*.jpg' -o -iname '*.xcf' \) -exec echo mv {} /new/path \;
Это ограничивает поиск обычными файлами ( -тип f
), а затем файлами, имена которых не имеют (!
) расширение *. png
в любом регистре ( -iname '* .png'
) или ( -o
) *. gif
, и скоро. Все расширения сгруппированы в одно условие между \ (... \)
. Для каждого совпадающего файла он запускает команду ( -exec
), которая перемещает файл, имя которого вставлено вместо {}
, в каталог / new / путь
. \;
сообщает find
, что команда завершена.
Замена имени происходит внутри кода выполнения программы, поэтому пробелы и другие специальные символы не имеют значения.
Если вы хотите сделать это прямо внутри Bash, вы можете использовать расширенные возможности Bash сопоставления с образцом . Для этого необходимо, чтобы shopt extglob
был включен, а также globstar
. В этом случае используйте:
mv **/!(*.[gG][iI][fF]|*.[pP][nN][gG]|*.[xX][cC][fF]|*.[jJ][pP][gG]) /new/path
Это соответствует всем файлам в подкаталогах ( **
), которые не соответствуют *. Gif
, *. Png
и т. Д. , в любой комбинации наборов символов и перемещает их на новый путь. Расширение выполняется оболочкой, поэтому пробелы и специальные символы снова не имеют значения.
Выше предполагается, что все файлы находятся в подкаталогах. В противном случае вы можете повторить часть после ** /
, чтобы также включить текущий каталог.
Подобные функции есть в zsh
и других оболочках, но вы указали, что используете Bash.
(Еще одно примечание: синтаксический анализ ls
никогда не бывает хорошей идеей - просто не пытайтесь.)
Во-первых, если в rsync и есть такая опция, я о ней не знаю и не могу найти ее на странице руководства. Это досадно, так как это быстро предоставит то, что вам нужно, и предположительно для любого возможного rsync
варианта использования.
Во-вторых, я думаю, что если бы кто-то попытался сделать это с существующими опциями rsync (в основном --сухой -запуск в сочетании с избытком возможных комбинаций контрольной суммы, дата -была бы -новее, дата -стала -старше, файл -должен -быть -удаленным, до бесконечности )потребуется несколько проходов rsync
, по одному для каждой возможной причины, по которой файл может получить rsync
изд. Это кажется громоздким для ваших целей.
Если вы можете работать с инструментом, который сравнивает два дерева и сообщает о различиях и интерполирует его вывод в соответствии с вашими потребностями, тогда mtree
может подойти для ваших нужд.
mtree
специально разработан для сравнения двух деревьев каталогов и сообщения о различиях.
На исходном компьютере создайте спецификацию mtree (, включая хэш sha256 )желаемого исходного дерева:
# mtree -K sha256 -cp /my_path > my_path.mtree
Затем rsync
просмотрите дерево и запустите mtree на удаленной машине, чтобы увидеть, совпадает ли путь дерева удаленных каталогов /remote _с локальным путем /my _:
# rsync -a --delete /my_path/ remote:/remote_path/
# ssh remote mtree -p /remote_path < my_path.mtree && echo match
match
Теперь давайте немного повозимся с удаленным деревом. Короче говоря, я создал целевой файл farkle
, которого не существует в источнике, удалил файл file.txt
и изменил метку времени в файле data.txt
.
# ssh remote mtree -p remote_path < my_path.mtree || echo fail
.: modification time (Wed Apr 17 10:49:32 2019, Wed Apr 17 11:55:10 2019)
extra: farkle
data.txt:
modification time (Wed Apr 17 10:45:02 2019, Wed Apr 17 11:56:27 2019)
foo: size (32, 29)
modification time (Tue Apr 16 10:16:44 2019, Wed Apr 17 11:53:18 2019)
sha256digest (0x6082aa7261362c4c71c82adf492bc724de53a5814e64b233c43c6775efeb1dd0, 0x2d2537ea27c27dfb2c1690c51c652b9ada32adc29a91b732c24939dcff371cd6)
./file.txt missing
fail
mtree
сообщает вам, что:
farkle
существует в пункте назначения, но не в источнике; это было бы удаляется, если вы укажете --удалить в командной строке rsync
. data.txt
не изменился ни по содержимому (, ни по хэшу sha256 ), ни по размеру, но более новая временная метка; копирование, основанное только на контрольной сумме, может не -повторно передать файл, а также rsync
не передать только «более новые» файлы, поскольку файл назначения теперь новее, чем исходный. file.txt
отсутствует на целевом хосте и, предположительно, rsync
будет передано при следующем запуске, если не будет какого-либо критерия исключения. Таким образом, это не совсем дает вам прямое объяснение от rsync о том, почему он копирует или не копирует то, что, по вашему мнению, должно, но действительно дает вам жесткий, поддающийся проверке отчет о том, что на самом деле происходит в отношении локальных и удаленных деревьев каталогов.
Если вы методично сохраните выходной файл my_path.mtree
, например, включив в имя файла отметку даты, вы также можете запустить mtree
на локальном компьютере, чтобы сравнить существующее дерево путей /my _с предыдущим запуском. (вчерашний? на прошлой неделе? ), чтобы увидеть, не изменилось ли что-то локально, чего вы, возможно, не ожидали.
mtree
включен в некоторые дистрибутивы Unix,но если у вас отсутствует mtree, мне удалось установить версию Арчи Коббса с GitHub .