Как получить последние файлы N в каталоге?

Ваш ответ, вероятно, там: http://www.techsupportalert.com/content/tips-and-tricks-mint-after-installation-mint-13-cinnamon-edition.htm#Install-Extra-Fonts

Таким образом для предоставления доступа к этому доступным Вам, вероятно, только придется работать fc-cache -f -v с корневыми правами.

15
26.01.2015, 22:03
6 ответов

У меня нет объяснения , почему они сделали это этим путем, но $ {: -foo...} действительно имеет применение: оно считается подстановкой параметров в местах, которые синтаксически требуют одного, но всегда просто расширяется до литерала вы даете. Для использования флагов расширения или других спецификаторов расширения можно создать следующие записи:

$ echo ${(#)${=${:-65 66 67}}}
A B C
$ echo ${(q)${:-hello world!}}
hello\ world\!

Можно также использовать другие расширения в слове последовательностей :

$ restofarglist=arg3,arg4
$ echo ${${:-arg1,arg2,$restofarglist}//,/ }

Все это поведение документировано прямо в конце раздела о расширении параметров :

Если выражение параметра типа $ {...} или подстановка команды типа $ (...) вместо name выше, оно расширяется первым и результат используется так, как если бы это было значение name .

Вы можете вложить эти расширения произвольно глубоко, хотя они становятся непонятными довольно быстро. Существуют странные угловые случаи, использующие семейство расширений $ {name = word} внутри любой стороны.

Это довольно тупой способ делать вещи в целом, но это и единственное приложение я знаю для $ {: -} и единственный способ сделать это вещи, не создавая другой переменной. Документация определенно может быть более четкой, даже несмотря на то, что все биты технически там.

-121--123217-

Если существуют только файлы и их имена не содержат пробелов или новых строк (и вы не изменили $ IFS ) или символов globe (или некоторых непечатаемых символов с некоторыми реализациями ls ), и не начинайтесь с . , то вы можете сделать это:

cp -- $(ls | tail -n 4) ~/
-121--28225-

Это можно легко сделать с помощью массивов bash/ksh93/zsh:

a=(*)
cp -- "${a[@]: -4}" ~/

Это работает для всех не скрытых имен файлов, даже если они содержат места, вкладки, новые строки или другие сложные символы (при условии, что в текущем каталоге есть по крайней мере 4 не скрытых файлов с bash )

Принцип работы

  • a = (*)

    Создается массив a со всеми именами файлов. Имена файлов, возвращаемые bash, сортируются в алфавитном порядке. (Я предполагаю, что это то, что вы имеете в виду под «упорядоченный по имени файла». )

  • $ {a [@]: -4}

    Это возвращает последние четыре элемента массива a (при условии, что массив содержит не менее 4 элементов с bash ).

  • cp -- «$ {a [@]: -4}» ~/

    Копирование последних четырех имен файлов в домашний каталог.

Для одновременного копирования и переименования

Это приведет к копированию последних четырех файлов только в домашний каталог и, одновременно, добавлению последовательности a _ к имени скопированного файла:

a=(*)
for fname in "${a[@]: -4}"; do cp -- "$fname" ~/a_"$fname"; done

Скопируйте из другого каталога и переименуйте

Если мы используем a = (./some_dir/*) вместо a = (*) , то возникает проблема с присоединением каталога к имени файла. Одним из решений является:

a=(./some_dir/*) 
for f in "${a[@]: -4}"; do cp "$f"  ~/a_"${f##*/}"; done

Другое решение состоит в использовании субоболочки и cd в директории в субоболочке:

(cd ./some_dir && a=(*) && for f in "${a[@]: -4}"; do cp -- "$f" ~/a_"$f"; done) 

По завершении субоболочки оболочка возвращает нас в исходную директорию.

Убедитесь, что упорядочение согласовано

Вопрос запрашивает файлы, «упорядоченные по имени файла». Этот порядок, указывает Оливье Дюлак в комментариях, будет варьироваться от одного языка к другому. Если важно иметь фиксированные результаты независимо от параметров настройки машины, то лучше указать языковой стандарт явно, когда определен массив a . Например,

LC_ALL=C a=(*)

Можно узнать, какой языковой стандарт используется в данный момент, выполнив команду языковой стандарт .

23
27.01.2020, 19:49

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

cp *(On[1,4]) ~/

Здесь On сортирует имена файлов в алфавитном порядке и [1,4] принимает только первые 4 из них.

С помощью можно сделать это более надежным, выбрав только простые файлы (за исключением каталогов, труб и т.д.). , а также добавлением -- к команде cp для правильной обработки файлов, имена которых начинаются с -:

cp -- *(.On[1,4]) ~

Добавьте квалификатор D, если вы также хотите рассматривать скрытые файлы (точечные файлы):

cp -- *(D.On[1,4]) ~
9
27.01.2020, 19:49

Еще один способ проверять возраст процесса, прежде чем убить его. Таким образом, вы можете убедиться, что вы не убиваете процесс, который не вырезан менее чем за 24 часа. Вы можете добавить , если состояние, основанное на этом перед убийством процесса.

if [[ $(ps -p $p -o etime=) =~ 1-. ]] ; then
    kill $p
fi

Это Если условие проверит, будет ли идентификатор процесса $ p менее чем за 24 часа (86400 секунд).

PS: - Команда PS -P $ P-etime = будет иметь формат -HH: MM: SS

-121--11384-

Если есть только файлы, и их имена не содержат пробела или новой строки (и вы не модифицировали $ IFS ) или шаблон [или некоторые непечатные символы с некоторыми реализациями LS ) и не начинай с . , тогда вы можете сделать это:

cp -- $(ls | tail -n 4) ~/
4
27.01.2020, 19:49

Вот решение, использующее чрезвычайно простые команды bash.

find . -maxdepth 1 -type f | sort | tail -n 4 | while read -r file; do cp "$file" ~/; done

Объяснение:

find . -maxdepth 1 -type f

Находит все файлы в текущем каталоге.

sort

Сортирует в алфавитном порядке.

tail -n 4

Показывает только последние 4 строки.

while read -r file; do cp "$file" ~/; done

Перебирает каждую строку, выполняя команду копирования.

7
27.01.2020, 19:49

Если вам нравится сортировка оболочки, вы можете просто сделать:

set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
cp "$@" /path/to/target/dir

Это очень похоже на bash - предлагается конкретное решение для массива, но оно должно быть переносимым в любую POSIX-совместимую оболочку. Некоторые примечания об обоих методах:

  1. Важно, чтобы ваши аргументы cp приводились с cp - , либо вы получите один из . точка или / в начале каждого имени. Если вы этого не сделаете, вы рискуете поставить дефис в начале - в первом аргументе cp , который может быть интерпретирован как опция и приведет к сбою операции или к непреднамеренному отображению результатов.

    • Даже если вы работаете с текущим каталогом в качестве исходного каталога, это легко сделать как ... set - ./* или array = (./*) .
  2. При использовании обоих методов важно убедиться, что у вас есть как минимум столько элементов в массиве arg, сколько вы пытаетесь удалить - я делаю это здесь с помощью математического расширения. Сдвиг происходит только в том случае, если в массиве arg есть как минимум 4 элемента - и затем смещаются только те первые аргументы, которые составляют излишек 4 ..

    • Таким образом, в случае набора 1 2 3 4 5 он сместит 1 прочь, но в случае набора 1 2 3 он сместит ничего такого.
    • Например: a = (1 2 3); echo "$ {a [@]: -4}" печатает пустую строку.

Если вы копируете из одного каталога в другой, вы можете использовать pax :

set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
pax -rws '|.*/|new_prefix|' "$@" /path/to/target/dir

... который применит sed -замена стиля для всех имен файлов при их копировании.

6
27.01.2020, 19:49

Это простое решение для bash без кода цикла.Скопируйте последние 4 файла из текущего каталога в место назначения:

$ find. -maxdepth 1 -type f |tail -n -4|xargs cp -t "$destdir"
1
27.01.2020, 19:49

Теги

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