Это довольно легко сделать с помощью инструмента переименования perl (, а НЕ инструмента переименования из пакета util -linux ). например.
Настройка:
$ touch 2019-05-01-00.34.00.msg 2019-05-02-00.36.00.msg 2019-06-14-01.38.00.msg
$ ls -l
total 2
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-05-01-00.34.00.msg
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-05-02-00.36.00.msg
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-06-14-01.38.00.msg
Переименовать:
rename -n '
use File::Path qw(make_path);
if (-f $_ && m/^\d{4}-\d{2}-\d{2}-/) {
my ($y,$m,$d,$f) = split /-/,$_,4;
make_path("$y/$m/$d");
$_ = "$y/$m/$d/$f";
}' *.msg
Этот сценарий начинается с игнорирования имен файлов, которые не являются обычными файлами(-f
)или не соответствуют шаблону ^YYYY-MM-DD-
. Это предотвращает создание нежелательных каталогов при вводе мусора.
Имя файла разбивается на четыре элемента. Первые 3 — это год, месяц и день, встроенные в имя файла ($y
, $m
и $d
), а 4-й — оставшаяся часть имени файла($f
).
Он использует функцию make_path()
из стандартного модуля Файл ::Путь для рекурсивного создания каталогов для YYYY/
, YYYY/MM/
и YYYY/MM/DD/
(, подобно опции -p
модуля команда mkdir
). Вместо этого я мог бы запустить Perl-функцию mkdir()
три раза, но предпочел использовать File::Path
.
Затем он переименовывает (, т.е. перемещает )файл в правильный каталог, устанавливая $_
равным"$y/$m/$d/$f"
Это ключ к тому, как работает perl rename
. Вы можете использовать любой perl-код, от простого s/foo/bar/
поиска в стиле -и -замены до сценариев, намного более сложных, чем тот, что в этом ответе. Если код изменится $_
, то файл будет переименован в это имя. Если $_
не изменено, оно не переименовывается.
ПРИМЕЧАНИЕ. :этот один -вкладыш использует вариант rename
и -n
, так что работает только всухую -. Чтобы он действительно переименовывал файлы, удалите -n
или измените его на -v
для подробного вывода, например:
2019-05-01-00.34.00.msg renamed as 2019/05/01/00.34.00.msg
2019-05-02-00.36.00.msg renamed as 2019/05/02/00.36.00.msg
2019-06-14-01.38.00.msg renamed as 2019/06/14/01.38.00.msg
Кстати, имена файлов могут быть предоставлены в команде -в строке (, как показано выше ), или путем передачи в сценарий(rename
имеет параметр -0
, чтобы он мог принимать ввод от, например find... -print0
или что-то еще, что может вывести список имен файлов, разделенных NUL -).
Наконец,rename
не будет не перезаписывать существующие файлы, если только вы не укажете это с помощью опции -f
, также известной как --force
.
У меня было
WorkingDirectory=/tmp/dir
ExecStartPost=/bin/rm /tmp/dir
ExecStartPost=/bin/sh -c "foo bar"
Один ExecStartPost
удалял рабочий каталог. Второй ExecStartPost
не смог попасть в этот каталог для запуска команды. Это ошибка, которая была сгенерирована.