Відповіді:
У bash або ksh введіть імена файлів у масив та повторіть цей масив у зворотному порядку.
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
Код вище також працює в zsh, якщо ksh_arrays
параметр встановлений (він знаходиться в режимі емуляції ksh). У zsh є більш простий метод, який полягає в тому, щоб змінити порядок поєдинків через глобальний класифікатор:
for f in /var/logs/foo*.log(On); do bar $f; done
POSIX не включає масиви, тому, якщо ви хочете бути портативними, ваш єдиний варіант безпосередньо зберігати масив рядків - це позиційні параметри.
set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
eval "f=\${$i}"
bar "$f"
i=$((i-1))
done
i
і f
; просто виконайте shift
, використовуйте $1
для свого дзвінка bar
та перевіряйте [ -z $1 ]
свій while
.
[ -z $1 ]
ні [ -z "$1" ]
корисні тести (що робити, якщо параметр був *
, або порожній рядок?). І в будь-якому випадку вони тут не допомагають: питання полягає в тому, як зациклюватися в протилежному порядку.
Спробуйте це, якщо ви не вважаєте розриви рядків "прикольними символами":
ls /var/logs/foo*.log | tac | while read f; do
bar "$f"
done
f
в моїй ситуації. Однак ця відповідь є значною мірою як заміна звичайного for
рядка.
Якщо хтось намагається зрозуміти, як повернути ітерацію через список рядків з обмеженим пробілом, це працює:
reverse() {
tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}
list="a bb ccc"
for i in `reverse $list`; do
echo "$i"
done
> ccc
> bb
> a
tac
є частиною GNU coreutils. Але ваше рішення також є хорошим.
tac
. Хоча з числа tac
безрезультатних відповідей тут я здогадуюсь, що, можливо, OSX не має tac. У такому випадку використовуйте якийсь варіант рішення @ arp - це все одно простіше зрозуміти.
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar
Потрібно працювати так, як вам хочеться (це було перевірено на Mac OS X, і в мене нижче застереження ...).
На сторінці чоловіка для пошуку:
-print0
This 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. Якщо ваші імена файлів містять нові рядки або інші дивні символи, пошук має це добре впоратися.
tail -r
приймає стандартний вхід через трубу і повертає його назад (зверніть увагу, що tail -r
друкується весь вхід у stdout, а не лише останні 10 рядків, що є стандартним за замовчуванням. man tail
Для отримання додаткової інформації).
Потім ми передаємо це xargs -0
:
-0 Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines. This is expected to be used in concert with the
-print0 function in find(1).
Тут xargs очікує на те, щоб побачити аргументи, розділені символом NUL, з якого ви перейшли find
та переймено tail
.
Мій застереження: Я читав, що tail
не добре співпадає з нульовими строками . Це добре працювало на Mac OS X, але я не можу гарантувати, що це стосується всіх * nixes. Стежте обережно.
Слід також зазначити, що паралель GNU часто використовується як xargs
альтернатива. Ви можете це також перевірити.
Можливо, мені чогось не вистачає, тому інші повинні задзвеніти.
tail -r
хоча я щось роблю не так?
tac
як альтернатива, тому я б спробував це, замість цього
tail -r
є специфічним для OSX, і обертає введений новий рядком вхід, а не введений нулем вхід. Ваше друге рішення взагалі не працює (ви працюєте з підключенням ls
, що не хвилює); не існує простого виправлення, яке б змусило його надійно працювати.
У вашому прикладі ви перебираєте декілька файлів, але я знайшов це питання через його більш загальний заголовок, який також може охоплювати циклічність через масив або реверсування на основі будь-якої кількості замовлень.
Ось як це зробити в Zsh:
Якщо ви перебираєте елементи в масиві, використовуйте цей синтаксис ( джерело )
for f in ${(Oa)your_array}; do
...
done
O
відміни порядку, зазначеного в наступному прапорі; a
- це нормальний порядок масиву.
За словами @Gilles, On
буде зворотний порядок сортування ваших globbed файлів, наприклад , з 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/outragerely-useful-tips- to master-your-z-shell /
Mac OSX не підтримує tac
команду. Рішення від @tcdyl працює, коли ви викликаєте одну команду в for
циклі. Для всіх інших випадків наступним є найпростіший спосіб обійти його.
Цей підхід не підтримує нових рядків у ваших іменах. Основна причина полягає в тому, що tail -r
впорядковується його введення як обмежене новими рядками.
for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done
Однак є спосіб обійти обмеження нового рядка. Якщо ви знаєте, що ваші назви файлів не містять певного символу (скажімо, '='), ви можете використовувати tr
для заміни всіх нових рядків, щоб стати цим символом, а потім виконувати сортування. Результат виглядатиме так:
for i in `find [directory] -name '[filename]' -print0 | tr '\n' '=' | tr '\0' '\n'
| tail -r | tr '\n' '\0' | tr '=' '\n' | xargs -0`; do [commands]; done
Примітка: залежно від вашої версії tr
, вона може не підтримуватись '\0'
як символ. Зазвичай це можна вирішити, змінивши локальну мову на C (але я не пам'ятаю, як саме, оскільки після її виправлення це працює зараз на моєму комп'ютері). Якщо ви отримаєте повідомлення про помилку, і ви не можете знайти вирішення, будь ласка, опублікуйте його як коментар, щоб я міг допомогти вам усунути його.
sort -r
доfor
або відмивати черезls -r
.