Короткий ответ: >
должен сопровождаться именем файла или &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. На самом деле, специальные символы как >
иногда замечаются сопровождаемые пространством. Даже при том, что это позволяется, две (разделенных пробелом) строки должны быть поняты как единственный 'объект'.
Попытайтесь выполнить его на экранной сессии. Или даже попробуйте другую конструкцию. Я верю, находят + 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}
Следующий - 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 вы можете отредактировать его, чтобы удалить ненужные файлы.
Я использую этот сценарий оболочки в корне каталога, заполненного файлами, чтобы переместить их все в структуру, подобную год / месяц
:
#!/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 в правильную структуру.
Я также сортирую изображения по каталогам, структурированным по дате, но у меня есть несколько другой подход. Я хочу, чтобы мои изображения переходили в соответствующие каталоги 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
У меня нет миллионов изображений для сортировки, и если бы у меня получилось, то этот код занял бы довольно много времени. Но он работает, как и предполагалось.