В bash или ksh поместите имена файлов в массив и переберите этот массив в обратном порядке.
files=(/var/logs/foo*.log)for((i=${#files[@]}-1; i>=0; i--));do
bar "${files[$i]}"done
Приведенный выше код также работает в zsh, если эта ksh_arraysопция установлена (он находится в режиме эмуляции ksh). В zsh есть более простой метод, который заключается в изменении порядка совпадений с помощью квалификатора glob:
for f in/var/logs/foo*.log(On);do bar $f;done
POSIX не включает в себя массивы, поэтому, если вы хотите быть переносимым, ваш единственный способ сохранить массив строк - это позиционные параметры.
set--/var/logs/foo*.log
i=$#while[ $i -gt 0];doeval"f=\${$i}"
bar "$f"
i=$((i-1))done
Как только вы используете позиционные параметры, вам не нужны ваши переменные iи f; просто выполните shift, используйте $1для вашего звонка barи протестируйте [ -z $1 ]в своем while.
user1404316
@ user1404316 Это был бы слишком сложный способ перебора элементов в порядке возрастания . Кроме того , не так: ни , [ -z $1 ]ни [ -z "$1" ]полезные тесты (что , если параметр был *, или пустая строка?). И в любом случае они здесь не помогают: вопрос в том, как сделать цикл в обратном порядке.
Жиль "ТАК - перестань быть злым"
В частности, вопрос говорит, что он перебирает имена файлов в / var / log, поэтому можно предположить, что ни один из параметров не будет "*" или пустым. Тем не менее, я исправлен в отношении обратного порядка.
user1404316
7
Попробуйте это, если только вы не считаете разрывы строк «прикольными символами»:
ls /var/logs/foo*.log | tac |while read f;do
bar "$f"done
Есть ли метод, который работает с переносами строк? (Я знаю, что это редко, но, по крайней мере, ради обучения я хотел бы знать, можно ли написать правильный код.)
Mehrdad
Творческий подход к использованию tac для изменения направления, и если вы хотите избавиться от некоторых нежелательных символов, таких как разрывы строк, вы можете передать по конвейеру tr -d '\ n'.
У меня нет так в моей системе; Я не знаю, надежен ли он, но я использовал для x в $ {mylist}; do revv = "$ {x} $ {revv}"; сделано
arp
@arp Это шокирует, так как tacявляется частью GNU coreutils. Но ваше решение тоже хорошее.
ACK_stoverflow
@ACK_stoverflow Существуют системы без инструментов пользователя Linux.
Кусалананда
@Kusalananda Вы говорите, что только Linux использует GNU coreutils? СМЕШНО. Даже busybox есть tac. Хотя по количеству tacответов здесь нет, я думаю, что, возможно, OSX не имеет TAC. В этом случае используйте какой-либо вариант решения @ arp - это легче понять в любом случае.
ACK_stoverflow
@ACK_stoverflow Это то, что я говорю, да.
Кусалананда
1
find /var/logs/-name 'foo*.log'-print0 | tail -r | xargs -0 bar
Должен работать так, как вы хотите (это было протестировано на Mac OS X, и у меня есть предупреждение ниже ...).
Со страницы руководства для поиска:
-print0This primary always evaluates to true.It prints the pathname of the current file to standard output, followed by an ASCII NUL character (charac-
ter code 0).
По сути, вы находите файлы, соответствующие вашей строке + glob, и заканчиваете каждый символом NUL. Если ваши имена файлов содержат символы новой строки или другие странные символы, команда find должна с этим справиться.
tail -r
принимает стандартный ввод через канал и переворачивает его (обратите внимание, что все вводимые данные tail -rпечатаются в стандартный вывод, а не только последние 10 строк, что является стандартным значением по умолчанию. для получения дополнительной информации).man tail
Затем мы передадим это xargs -0:
-0Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines.This is expected to be used in concert with the-print0 functionin find(1).
Здесь xargs ожидает увидеть аргументы, разделенные символом NUL, который вы передали findи отменили tail.
+1 отличный ответ. Похоже, Ubuntu не поддерживает tail -r... я делаю что-то не так?
Мердад
1
Нет, я так не думаю. У меня не работает мой linux-компьютер, но быстрый поиск по запросу «linux tail man» не показывает его в качестве опции. Сунаку упоминается tacв качестве альтернативы, поэтому я бы попробовал вместо этого
tcdyl
Я также отредактировал ответ, чтобы включить другую альтернативу
tcdyl
Ой, я забыл +1, когда сказал +1: Готово! Извините за это, ха-ха :)
Mehrdad
4
tail -rспецифичен для OSX и инвертирует ввод с разделителями новой строки, а не ввод с нулем. Ваше второе решение вообще не работает (вы вводите данные ls, это не важно); нет простого решения, которое могло бы сделать его надежным.
Жиль "ТАК - перестань быть злым"
1
В вашем примере вы перебираете несколько файлов, но я нашел этот вопрос из-за его более общего заголовка, который также может охватывать зацикливание над массивом или реверсирование на основе любого количества порядков.
Вот как это сделать в Zsh:
Если вы перебираете элементы массива, используйте этот синтаксис ( источник )
for f in ${(Oa)your_array};do...done
Oменяет порядок, указанный в следующем флаге; aнормальный порядок массива.
Как сказал @Gilles, Onобратный порядок ваших файлов, например, с my/file/glob/*(On). Это потому, что Onэто «обратный порядок имен ».
Mac OSX не поддерживает tacкоманду. Решение @tcdyl работает, когда вы вызываете одну команду в forцикле. Для всех остальных случаев следующее - это самый простой способ обойти это.
Этот подход не поддерживает наличие новых строк в ваших именах файлов. Основная причина заключается в том, что tail -rсортирует входные данные как разделенные символами новой строки.
for i in`ls -1 [filename pattern] | tail -r`;do[commands here];done
Однако есть способ обойти ограничение новой строки. Если вы знаете, что ваши имена файлов не содержат определенный символ (скажем, '='), то вы можете использовать trдля замены всех новых строк, чтобы стать этим символом, а затем выполнить сортировку. Результат будет выглядеть следующим образом:
Примечание: в зависимости от вашей версии tr, он может не поддерживать '\0'как символ. Обычно это можно обойти, изменив локаль на C (но я не помню как именно, так как после исправления однажды она теперь работает на моем компьютере). Если вы получаете сообщение об ошибке и не можете найти обходной путь, то, пожалуйста, опубликуйте его как комментарий, чтобы я мог помочь вам устранить его.
sort -r
передfor
или отмытьls -r
.Ответы:
В bash или ksh поместите имена файлов в массив и переберите этот массив в обратном порядке.
Приведенный выше код также работает в zsh, если эта
ksh_arrays
опция установлена (он находится в режиме эмуляции ksh). В zsh есть более простой метод, который заключается в изменении порядка совпадений с помощью квалификатора glob:POSIX не включает в себя массивы, поэтому, если вы хотите быть переносимым, ваш единственный способ сохранить массив строк - это позиционные параметры.
источник
i
иf
; просто выполнитеshift
, используйте$1
для вашего звонкаbar
и протестируйте[ -z $1 ]
в своемwhile
.[ -z $1 ]
ни[ -z "$1" ]
полезные тесты (что , если параметр был*
, или пустая строка?). И в любом случае они здесь не помогают: вопрос в том, как сделать цикл в обратном порядке.Попробуйте это, если только вы не считаете разрывы строк «прикольными символами»:
источник
f
в моей ситуации. Этот ответ, тем не менее, действует в качестве замены для обычнойfor
линии.Если кто-то пытается выяснить, как отменить итерацию в списке строк, разделенных пробелами, это работает:
источник
tac
является частью GNU coreutils. Но ваше решение тоже хорошее.tac
. Хотя по количествуtac
ответов здесь нет, я думаю, что, возможно, OSX не имеет TAC. В этом случае используйте какой-либо вариант решения @ arp - это легче понять в любом случае.Должен работать так, как вы хотите (это было протестировано на Mac OS X, и у меня есть предупреждение ниже ...).
Со страницы руководства для поиска:
По сути, вы находите файлы, соответствующие вашей строке + glob, и заканчиваете каждый символом NUL. Если ваши имена файлов содержат символы новой строки или другие странные символы, команда find должна с этим справиться.
принимает стандартный ввод через канал и переворачивает его (обратите внимание, что все вводимые данные
tail -r
печатаются в стандартный вывод, а не только последние 10 строк, что является стандартным значением по умолчанию. для получения дополнительной информации).man tail
Затем мы передадим это
xargs -0
:Здесь xargs ожидает увидеть аргументы, разделенные символом NUL, который вы передали
find
и отменилиtail
.Мое предостережение: я читал, что
tail
это не очень хорошо для строк с нулевым символом в конце . Это хорошо работало на Mac OS X, но я не могу гарантировать, что это относится ко всем * nixes. Действуй осторожно.Следует также отметить, что GNU Parallel часто используется в качестве
xargs
альтернативы. Вы можете проверить это тоже.Я могу что-то упустить, поэтому другие должны вмешиваться.
источник
tail -r
... я делаю что-то не так?tac
в качестве альтернативы, поэтому я бы попробовал вместо этогоtail -r
специфичен для OSX и инвертирует ввод с разделителями новой строки, а не ввод с нулем. Ваше второе решение вообще не работает (вы вводите данныеls
, это не важно); нет простого решения, которое могло бы сделать его надежным.В вашем примере вы перебираете несколько файлов, но я нашел этот вопрос из-за его более общего заголовка, который также может охватывать зацикливание над массивом или реверсирование на основе любого количества порядков.
Вот как это сделать в Zsh:
Если вы перебираете элементы массива, используйте этот синтаксис ( источник )
O
меняет порядок, указанный в следующем флаге;a
нормальный порядок массива.Как сказал @Gilles,
On
обратный порядок ваших файлов, например, сmy/file/glob/*(On)
. Это потому, чтоOn
это «обратный порядок имен ».Zsh сортировать флаги:
a
порядок массиваL
длина файлаl
количество ссылокm
дата модификацииn
название^o
обратный порядок (o
нормальный порядок)O
обратный порядокДля примеров см. Https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt и http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- в мастер-ваш-Z-оболочка /
источник
Mac OSX не поддерживает
tac
команду. Решение @tcdyl работает, когда вы вызываете одну команду вfor
цикле. Для всех остальных случаев следующее - это самый простой способ обойти это.Этот подход не поддерживает наличие новых строк в ваших именах файлов. Основная причина заключается в том, что
tail -r
сортирует входные данные как разделенные символами новой строки.Однако есть способ обойти ограничение новой строки. Если вы знаете, что ваши имена файлов не содержат определенный символ (скажем, '='), то вы можете использовать
tr
для замены всех новых строк, чтобы стать этим символом, а затем выполнить сортировку. Результат будет выглядеть следующим образом:Примечание: в зависимости от вашей версии
tr
, он может не поддерживать'\0'
как символ. Обычно это можно обойти, изменив локаль на C (но я не помню как именно, так как после исправления однажды она теперь работает на моем компьютере). Если вы получаете сообщение об ошибке и не можете найти обходной путь, то, пожалуйста, опубликуйте его как комментарий, чтобы я мог помочь вам устранить его.источник
простой способ использования,
ls -r
как упомянуто @David Schwartzисточник
Попробуй это:
Я думаю, что это самый простой способ.
источник
for
петли в обратном порядке».