Как скопировать или переместить файлы -n уровня вверх на OSX через оболочку

Как я могу найти все файлы определенного типа / имени и скопировать их на уровень выше? Вот древовидная структура файловой системы:

germany/
       |
       adventure/
                |
                300x600/
                |      |
                |      file1.jpg
                |      file2.zip
                |
                400x600/
                       |
                       file8.jpg
                       file4.zip
switzerland/
           |
           adventure/...

Есть много страновых папок, около 20, и файлы.zip не гарантированно будут иметь 3 уровня глубины. Я в настоящее время в их родительской папке, countries/ и я хочу найти и скопировать все .zip файлы на один уровень вверх, на adventure/ каталог соответствующей страны / папки.

Я старался:

find . -type f -name '*.zip' -exec mv {}/.. \;

но тот с треском провалился. Он перемещал каждый файл на один уровень вверх, затем они снова перемещались на один уровень вверх.

Спасибо!

РЕДАКТИРОВАТЬ: я немного поиграл с решениями из ответов и прочитал много man страницы:). Наконец, я принял решение, которое мне понравилось больше всего, так как оно элегантное и не зависит от оболочки.

Что-то я все еще пытаюсь выяснить:

  1. Есть ли find работать как цикл или фигурные скобки считаются списком / массивом в других языках программирования? Значение: он заполняется найденными результатами (т. Е. Строками) одновременно и ТО передается команде -exec ?
  2. Почему движение сначала произошло на один уровень вверх, а затем снова на один уровень вверх?
  3. Есть ли способ сразу сказать mv/cp перейти на -n уровни [вверх / вниз]?

3 ответа

Решение

Вы можете сделать его независимым от оболочки и объединить его в один find команда:

find . -type f -name '*.zip' -exec \
sh -c 'echo cp -- "$0" "$(dirname "$0")"/..' {} \;

Удалить echo когда вы уверены, что он делает то, что вы хотите.

использование find чтобы найти файлы. Выполнить оболочку с -exec sh -c, передав найденный файл с {} в качестве первого аргумента этой оболочки. Поэтому в оболочке путь к файлу будет доступен как $0,

Вы можете использовать dirname "$0" и подстановка команды ($(…)), чтобы получить родительский каталог файла. Добавить как можно больше /.. как вы хотите пройти выше.

Обратите внимание, что я цитировал имена файлов, чтобы предотвратить неправильное расширение файлов с символами новой строки или пробелами в их имени.

Попробовал это с ubuntu zsh 5.0.2:

for pdir in */
do
  cd $pdir
  for dir in */
  do
    cd $dir
    mv */*.zip .
    cd ..
  done
  cd ..
done

Просто быстрая альтернатива, если реальность так проста, как приведенный пример:

cd germany
mv */*/*.zip .

(и там не миллионы файлов)

Другие вопросы по тегам