Команда для создания последовательно пронумерованных предназначенных каталогов и пакета перемещает файлы

Я создаю видео таймлапса путем разделения видео на отдельные изображения, использования G'MIC через командную строку для усреднения каждых 7 кадров, затем произвожу результаты к новым изображениям, которые приведут к кадрам для таймлапса (этот способ, которым я получаю шумовое бесплатное видео, которое выглядит большим). Поскольку можно предположить, что у меня есть много кадров - несколько тысяч отдельных изображений в каталоге, названном последовательно (image1.tiff, image2.tiff, и т.д.). Я нашел сценарий, который работает отлично на перемещение файлов - однажды...

k=1; find source/ -type f | while read file; do
     [[ k++ -le 7 ]] && mv "$file" target/ 
done 

В чем я нуждаюсь, теперь должен сделать этот сценарий

  1. повторитесь, пока все файлы не перемещены и
  2. создайте последовательно пронумерованные целевые каталоги (1, 2, 3, и т.д.), поскольку это идет так, я заканчиваю с несколькими сотнями каталогов каждый с 7 изображениями внутри.

Просто для уточнения каталог 1 должен содержать изображения 1-7, каталог 2 должен содержать изображения 8-14 и т.д.

Любая справка значительно ценится, я в значительной степени застреваю с этим.

4
задан 29 December 2014 в 00:39

5 ответов

(Python) сценарий ниже создает sub папки и организует Ваши файлы в папки:

Дополнительно:

  • сценарий вычисляет количество папок и добавляет начальные нули к именам папок для надлежащей сортировки (так как Вы упомянули тысячи файлов, имея в виду сотни папок)
  • , количество файлов на папку может варьироваться, в зависимости от Вашей установки по заголовку сценария

, который принимает сценарий:

  • Все файлы имеют расширение, все файлы имеют тот же расширение
  • , Ваши файлы называют image1.tiff, image2.tiff и т.д. (никакие начальные нули).

сценарий

#!/usr/bin/env python3
import os
import math
import shutil
#---
directory = "/path/to/files"      # path to your files
n_perfolder = 7                   # number of files per sub folder
#--
# creating file list, extension
f_list = os.listdir(directory); ext = f_list[0].split(".")[-1]
# calculate number of folders
n_folders = math.ceil(len(f_list)/n_perfolder)
# creating folder names, including leading zeros
folders = [str(fn+1) for fn in range(n_folders)]
fl_names = [(len(max(folders, key=len))-len(fl))*"0"+fl for fl in folders]
# creating folders and allocate files 
for i in range(len(fl_names)):
    mkfolder = directory+"/"+fl_names[i]
    if not os.path.exists(mkfolder):
        os.makedirs(mkfolder)
        r = range(i*n_perfolder+1, i*n_perfolder+n_perfolder+1)
        for n in r:
            try:
                file = directory+"/"+"image"+str(n)+"."+ext
                target = mkfolder+"/"+"image"+str(n)+"."+ext
                shutil.copyfile(file, target)
            except FileNotFoundError:
                pass

, Как использовать

Копия сценарий в пустой файл в главном разделе, установил каталог на Ваши файлы и количество файлов на подкаталог, сохраняет его как organize.py.

Выполнение это командой:

python3 /path/to/organize.py

Примечание

, Если Вы хотели бы к перемещение файлы вместо копирования, заменяет строку:

shutil.copyfile(file, target)

:

shutil.move(file, target)

(возражают против отступа!)

3
ответ дан 17 November 2019 в 03:59

Можно использовать xargs (-n или - макс.-args) для определения номера файлов для перемещения, но иметь в виду, что аргументы ограничены ARG_MAX.

#!/bin/bash

images="./source/image*.tiff"
target="./target"

ls -v $images | xargs -n 7 | while read -a files; do mkdir $target/$((++n)) && mv -t $target/$n ${files[@]}; done
0
ответ дан 17 November 2019 в 03:59

Если Вы не возражаете против того, чтобы это было перемещенным отдельно:

#! /bin/bash
for ((i = 1; ; i++))
do
    mkdir -p target-$i
    for j in $(seq $((i*7 - 6)) $((i*7)))
    do
        mv -t "target-$i" "source/image$j.tiff" || exit 1
    done
done

Или, более краткий:

find source -type f -name 'image*.tiff' -print0 | \
  sort -z --version-sort | \
  xargs -0n7 bash -c 'TARGET=target-$((${1//[^0-9]/} / 7 + 1)); \
    echo mkdir -p "$TARGET"; \
    echo mv -t "$TARGET" "$@"' move-7

Объяснение:

  1. -print0 печатает имена файлов, разделенные NUL (\0) символ. Это - самый безопасный способ передать имена файлов как вывод к другим командам.
  2. sort с -z ищет nul-разграниченный вход, и вид версии позволяет нам безопасно числам переменной длины вида, так, чтобы image2.tiff прибывает прежде image119.tiff
  3. xargs может ограничить количество аргументов, относился к каждой команде с -n, таким образом, здесь мы используем -n7. -0 для nul-разграниченного входа.
  4. Мы извлекаем частное числа первого аргумента $((${1//[^0-9]/} / 7 + 1)) - ${1//[^0-9]/} удаляет все в аргументе, который не является числом. Целочисленное деление гарантирует, чтобы мы получили частное.
  5. Это должно быть быстрее, так как мы выполняем точно количество mvs требуемый.

Осмотрите команды, произведенные, и если они смотрят хорошо, выполняют его снова после удаления echos.

KasiyA имеет интересную модификацию к этому.


Ответ JJOAO приносит rename возражать. Во-первых, сделайте все каталоги:

FILES=(source/image*.tiff)
COUNT=${#FILES[@]}
DIR_NUM=$((COUNT / 7 + 1))
seq 1 $DIR_NUM | xargs bash -c 'mkdir -p "${@/#/target-}"'

rename -n 's;source/image(\d+)\.tiff$;"target-".int($1 / 7 - 1)."/image".$1.".tiff";e' source/image*.tiff

На самом деле мы могли применить первые четыре строки ко всем решениям здесь и пропустить повторное mkdir -p.

2
ответ дан 1 December 2019 в 09:09
sevenfile=0
newdir=1
for file in `ls -v /path/to/source/image*.tiff` ; do
    mkdir -p "$newdir" && mv "$file" "$newdir" 
    [[ ++sevenfile -eq 7 ]] && sevenfile=0 &&  ((newdir++))
done
  • ls -v команда сортирует файлы как естественный вид (версии) числа.
    Можно проанализировать ls команда в этом Вашем случае, потому что все файлы конкретны и только image*.tiff.
  • mkdir -p $newdir упаковывает каталог в ящики на основе newdir переменная.

  • mv "$file" "$newdir" перемещает файл в каталог который newdir указывает.

  • Сбросьте sevenfile=0 обнулять, когда 7 файлов был перемещен ([[ ++sevenfile -eq 7 ]]) и инкремент к newdir значение.

Обратите внимание на те изменения /path/to/source/ к Вашему фактическому исходному каталогу.

Если Вы не хотите анализировать ls команда и если имя файлов включая пробелы, новые строки и и т.д.:

find /path/to/source/ -type f -name 'image*.tiff' -print0 | \
     sort -z --version-sort | while IFS= read -d '' -r file; do \
     mkdir -p "$newdir" && mv "$file" "$newdir" ;
     [[ ++sevenfile -eq 7 ]] && sevenfile=0 &&  ((newdir++));
done
2
ответ дан 1 December 2019 в 09:09
#!/usr/bin/perl

open(F,"-|","ls source/*") or die;

while(<F>){ chomp;
  if(/(\d+).tiff/){
     $dir= "target-" . (1+int($1/7));
     mkdir($dir) unless -d $dir;
     system "mv $_ $dir";
  }
}
1
ответ дан 1 December 2019 в 09:09

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

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