Рекурсивно переместите файлы в подкаталогах

.
├── subdirectory-A
│  ├── 1.jpg
│  ├── 1.tif
│  ├── 2.jpg
│  ├── 2.tif
│  ├── JPEG
│  └── TIF
└── subdirectory-B
    ├── 1.jpg
    ├── 1.tif
    ├── 2.jpg
    ├── 2.tif
    ├── JPEG
    └── TIF

Кто-либо может помочь? Я пытаюсь найти способ переместить все .tif файлы в каталог TIF и все .jpg файлы в каталог JPEG путем выполнения (mv) в сценарии оболочки из локального родительского каталога. Я использовал

mv *.jpg JPEG/

в каждом подкаталоге, но я должен сделать это задание на архиве с по 17K каталогам и ручной опции, один dir за один раз не является опцией.

3
задан 19 March 2019 в 14:43

3 ответа

Можно сделать это с rename использование bash globstar опция:

shopt -s globstar
rename -n 's/.*\//$&JPEG\//' **/*.jpeg
rename -n 's/.*\//$&TIF\//' **/*.tif

-n опция позволяет ему просто произвести то, что это сделает, удалит его для фактического выполнения перемещения. Что происходит, вот это rename пробегается через каждого, например. .jpeg файл в любом подкаталоге благодаря ** соответствие любому количеству подкаталогов. Это заменяет своим путем (все до последнего /) с собой ($&) сопровождаемый JPEG/, эффективно перемещая файл в этот каталог.

Если Ваш список аргументов будет слишком длинным, то команды выше бросят ошибку. Используйте этот подход для работы вокруг оболочки ARG_MAX предел:

printf '%s\0' **/*.jpeg | xargs -0 rename -n 's/.*\//$&JPEG\//'
printf '%s\0' **/*.tif | xargs -0 rename -n 's/.*\//$&TIF\//'

Это использует встроенную оболочку printf создавать разграниченный нулем список аргументов, который передается по каналу к xargs который звонит rename с максимальным количеством аргументов.

Пример выполняется

$ tree
.
├── subdirectory-A
│  ├── 1.jpeg
│  ├── 1.tif
│  ├── 2.jpeg
│  ├── 2.tif
│  ├── JPEG
│  └── TIF
└── subdirectory-B
    ├── 1.jpeg
    ├── 1.tif
    ├── 2.jpeg
    ├── 2.tif
    ├── JPEG
    └── TIF
$ shopt -s globstar
$ rename -n 's/.*\//$&JPEG\//' **/*.jpeg
rename(subdirectory-A/1.jpeg, subdirectory-A/JPEG/1.jpeg)
rename(subdirectory-A/2.jpeg, subdirectory-A/JPEG/2.jpeg)
rename(subdirectory-B/1.jpeg, subdirectory-B/JPEG/1.jpeg)
rename(subdirectory-B/2.jpeg, subdirectory-B/JPEG/2.jpeg)
$ rename 's/.*\//$&JPEG\//' **/*.jpeg
$ printf '%s\0' **/*.tif | xargs -0 rename 's/.*\//$&TIF\//'
$ tree
.
├── subdirectory-A
│  ├── JPEG
│  │  ├── 1.jpeg
│  │  └── 2.jpeg
│  └── TIF
│  ├── 1.tif
│  └── 2.tif
└── subdirectory-B
    ├── JPEG
    │  ├── 1.jpeg
    │  └── 2.jpeg
    └── TIF
        ├── 1.tif
        └── 2.tif
2
ответ дан 17 November 2019 в 09:37

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

#!/bin/bash
for dir in */     # or use: subdirectory*/
do
    cd "$dir"
    mv *jpg JPG/
    mv *tif TIF/
    cd ..
done

Пример использования как встроенная команда:

$ mkdir -p subdirectory-{A,B}/{TIF,JPG}; touch subdirectory-{A,B}/{1,2}.{jpg,tif}

$ for dir in */; do cd "$dir"; mv *jpg JPG/; mv *tif TIF/; cd ..; done

$ tree
.
├── subdirectory-A
│  ├── JPG
│  │  ├── 1.jpg
│  │  └── 2.jpg
│  └── TIF
│  ├── 1.tif
│  └── 2.tif
└── subdirectory-B
    ├── JPG
    │  ├── 1.jpg
    │  └── 2.jpg
    └── TIF
        ├── 1.tif
        └── 2.tif

6 directories, 8 files

Связанные вопросы:

2
ответ дан 17 November 2019 в 09:37

Так как Вы упомянули "по 17K каталогам", find и xargs прийти на ум.

# do this part Only Once  
cat >./TheScript <<"EOF"
#!/bin/bash
while $# -gt 0 ; do
    cd "$1"
    find . -maxdepth 1 -type f -name '*.jpg' -print | xargs --no-run-if-empty mv --target-directory=JPG
    find . -maxdepth 1 -type f -name '*.tif' -print | xargs --no-run-if-empty mv --target-directory=TIF
    cd "$OLDPWD"
    shift
done
exit 0
EOF
chmod +x ./TheScript
# end of "Only Once"


find . -type d \! -name 'JPG' -a \! -name 'TIF` -print |\
    xargs $PWD/.TheScript
2
ответ дан 17 November 2019 в 09:37

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

Похожие вопросы: