Переместитесь огромное количество файлов в дату структурировало порядок каталога

Короткий ответ: > должен сопровождаться именем файла или &n (n число), и | должен сопровождаться другим вызовом команды.


Подробнее: В синтаксисе оболочки вызов к некоторой команде содержит несколько компонентов. Пример:

A=foo 2>/dev/null B=bar cmd arg1 arg2 >file 3>&4 arg3

Здесь, параметры 2>/dev/null, >file и 3>&4 специальные параметры (содержащий незавершенное >¹), они используются для установления io-перенаправлений и могут появиться где угодно в командной строке. Filedesciptor 2 перенаправляется к /dev/null, filedescriptor 1 (неявный) перенаправляется к file и filedescriptor 3 перенаправляется к тому, с чем был связан filedescriptor 4.

Затем среди остающихся параметров, A=foo и B=bar содержать =, таким образом, их не рассматривают как название команды: они дают определенные значения переменным среды процесса, который будет запущен.

Затем прибывает команда cmd и реальные аргументы: arg1, arg2, arg3.

Канал | не часть вызова команды, она соединяет два таких вызова. Пример:

CC=gcc make 2>&1 | LESS=--quit-at-eof less

Вывод на filedescriptor 1 первым процессом будет получен, как введено на filedescriptor 0 вторым процессом через “канал”, который действует как буфер.


1. На самом деле, специальные символы как > иногда замечаются сопровождаемые пространством. Даже при том, что это позволяется, две (разделенных пробелом) строки должны быть поняты как единственный 'объект'.

5
18.04.2012, 02:27
4 ответа

Попытайтесь выполнить его на экранной сессии. Или даже попробуйте другую конструкцию. Я верю, находят + sed, будет работать лучше затем чистый удар:

find images/ -name "*.jpg" | sed 's%^[^_]*_[^_]*_\([0-9][0-9][0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\).*%mkdir -p "/home/username/sorted/\1/\2/\3/\4" \&\& mv "&" "/home/username/sorted/\1/\2/\3/\4/"%'

Это должно только показать, как sed делают команды для выполнения. Добавление e после в последний раз % вызовет выполнение команды:

find images/ -name "*.jpg" | sed 's%^[^_]*_[^_]*_\([0-9][0-9][0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\).*%mkdir -p "/home/username/sorted/\1/\2/\3/\4" \&\& mv "&" "/home/username/sorted/\1/\2/\3/\4/"%e'

PS. Вы не должны использовать в ударе

day=$(echo $fullyear |cut -c7-8)

Bash может сделать это само без echo | cut :

day=${fullyear:6:2}
5
27.01.2020, 20:39
  • 1
    я никогда не знал о команде sed. Отрывок, который Вы дали работам отлично... хорошо, это работало далеко в течение последних нескольких минут, генерируя папки и перемещая файлы в правильный порядок. Это было моим первым разом, когда-либо создающим *, отклоняют сценарий, я происхожу из Windows. Сервер, с которым я соединяюсь, является поставщиком веб-хостинга, не моим, таким образом, я могу только использовать Шпаклевку для соединения. –  PadraigD 17.04.2012, 16:13
  • 2
    я также не знал, что Bash может сделать сегментацию переменных. Это хорошо для знания. Большое спасибо за Вашу справку Rush. –  PadraigD 17.04.2012, 16:19
  • 3
    Это повредится ужасно на специальных символах в именах файлов и является также дырой в системе безопасности, поскольку она позволяет злонамеренным именам файлов вызывать выполнение произвольного кода. Посмотрите, Почему является цикличное выполнение по выводу находки плохой практикой? А-ч –  Wildcard 15.11.2016, 00:22

Следующий - liner создаст сценарий оболочки для перемещения файлов в нужную папку в зависимости от времени изменения.

find . -type f -not -name ".DS*" -exec stat -f "mkdir -p %Sm; mv \"%N\" %Sm" -t "%Y/%m/%d" {} \; > move.sh
sh move.sh

Я исключил файлы .DS * (-не -name ".DS *") Перед выполнением move.sh вы можете отредактировать его, чтобы удалить ненужные файлы.

0
27.01.2020, 20:39

Я использую этот сценарий оболочки в корне каталога, заполненного файлами, чтобы переместить их все в структуру, подобную год / месяц :

#!/usr/bin/env bash

if [ ! $1 ]; then
    echo "Usage: ./pictures.sh jpg"
    exit 1
fi

for f in *."$1"; do
    FILENAME="$f"
    YEAR=`date -j -f "%s" $(stat -f "%m" "$FILENAME") +"%Y"`
    MONTH=`date -j -f "%s" $(stat -f "%m" "$FILENAME") +"%m_%B"`
    DEST="$YEAR/$MONTH"

    if [ ! -d "$DEST" ]; then
        mkdir -p "$DEST"
    fi

    echo "Moving $FILENAME to $DEST/$FILENAME ..."
    mv "$FILENAME" "$DEST/$FILENAME"
done

Использование: $ ./pictures .sh JPG , чтобы переместить * .JPG в правильную структуру.

1
27.01.2020, 20:39

Я также сортирую изображения по каталогам, структурированным по дате, но у меня есть несколько другой подход. Я хочу, чтобы мои изображения переходили в соответствующие каталоги YYYY-MM, основываясь на их временных метках. Поэтому я начинаю с ls -l *.jpg > tmp.txt папки с изображениями, затем подаю эту tmp.txt в цикл, чтобы получить метку времени для каждого файла. Иначе я не нашел способа получить временную метку.

Вот мой код:

#!/bin/bash
hostdir="/home/Photos/"
destdir="/tmp/sorted"

cd $hostdir

touch /tmp/tmpsort.txt
ls -l *.jpg > /tmp/tmpsort.txt

while read line
do
    filename=$(echo $line | awk '{print $8}')
    filedate=$(echo $line | awk '{print $6}')
    filedir=${filedate:0:7}

    if [ ! -d $destdir/$filedir ]; then
        mkdir -p $destdir/$filedir
    fi

    # Let's skip files that were already sorted from a previous run
    if [ ! -f $destdir/$filedir/$fiename ]; then
        cp $filename $destdir/$filedir/
    fi

done < /tmp/tmpsort.txt
rm /tmp/tmpsort.txt

У меня нет миллионов изображений для сортировки, и если бы у меня получилось, то этот код занял бы довольно много времени. Но он работает, как и предполагалось.

0
27.01.2020, 20:39

Теги

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