Действительно ли возможно переименовать файлы, выбранные ls?

У меня есть некоторые файлы, которые я недавно загрузил, и я хочу назвать. Возможно сделать что-то как:

rename 's/ /_/g' $(ls -t | head -n5) 

На самом деле я хотел бы переименовать в последний раз загруженный 5 файлов.

Какая-либо идея?

2
задан 28 April 2017 в 11:50

3 ответа

Во-первых, я должен отметить, анализируя ls обычно не рекомендуется. Его вывод предназначен для потребления человеком, и это решение перестанет работать для некоторых законных имен файлов (как те, которые содержат символы новой строки, например),

После этих слов простое решение, действительно кажется, использует ls (как find не предлагает sort-by-modification-date опции). Для этого можно использовать каналы и xargs команда для выполнения финала переименовывает.

Короче говоря:

ls -1t | head -n5 | xargs -I {} rename 's/ /_/g' {}

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

Протесты

Это должно работать - но парсинг ls хрупко. Это повреждается для имен файлов, которые содержат символ новой строки; с помощью команды это предназначено для парсинга как find было бы намного лучше.

Однако я не знаю, как отсортировать по дате последнего изменения с find. Если кто-то еще знает, как сделать это, Вы, вероятно, закончили бы с чем-то как:

find . -mindepth 1 -maxdepth 1 -print0 | sort <???> -Z | head -z -n5 | xargs -0 rename 's/ /_/g'

Если <???> если бы допустимый аргумент были, то сказала бы эта цепочка команды find к выходным файлам в текущем каталоге, разделенном с символом NUL, и затем sort, head, и xargs все принял бы это как deliminator, а не новую строку - создание целого намного более последовательного процесса. Не стесняйтесь комментировать или редактировать это, если Вы знаете, как сделать это и хотеть заменить ls ответ с этой нижней частью.

2
ответ дан 2 December 2019 в 02:47

Как уже говорилось парсинг ls хрупок . Это повредится, если Ваши имена файлов будут иметь какой-либо тип странности (пробелы, новые строки, управляющие символы и т.д.). Так как Вы хотите заменить пробелы _, Ваш предложенный подход перестанет работать. Безопасный способ сделать это было бы:

stat --printf '%n/%Y\0' * | sort -rz -t'/' -k 2 | head -z -n 3 | 
    cut -d'/' -z -f 1 | xargs -0 perl-rename 's/ /_/g'
  • stat --printf '%n/%Y\0' *: это распечатает имя (%n) из каждого файла или каталога в текущем каталоге, сопровождаемом наклонной чертой (/; я использую наклонную черту, так как это не позволяется в имени файла, так может безопасно использоваться в качестве разделителя), и время изменения файла в секундах с эпохи (%Y) и наконец Нулевой символ (\0).
  • sort -rz -k 2: это возьмет РАЗДЕЛЕННЫЙ ОТ ПУСТОГО УКАЗАТЕЛЯ, вводит (-z) и сортируют его в обратном порядке (-r) на основе значения во втором / - разделенное поле (-t'/') каждой строки (-k 2).
  • head -z -n 5: сохраните первое 5 (-n 5) разделенным от пустого указателя (-z) строки.
  • cut -d'/' -z -f 1: распечатайте 1-е (-f 1) / - разделенное поле (-d /) разграниченных пустым указателем (-z) данные.
1
ответ дан 2 December 2019 в 02:47

Я просто дал ls -q попытка:

IFS='
'
for file in `ls -tr1q|tail -n5`; do
  rename 's/ /_/g' "$file"
done

Делает желаемое, переименовывают, даже для имен файлов с новой строкой или другими управляющими символами, хотя она дает ошибку:

Unsuccessful stat on filename containing newline at /usr/bin/rename line 59

(с perl v5.20.2)

0
ответ дан 2 December 2019 в 02:47

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

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