Спасибо, что указали мне на другую связанную тему .
Для меня ключевым было использование переменной BASH _ENV.
Как отмечено в справочном руководстве по bash, существует несколько способов открыть оболочку , один из которых вызывал у меня затруднения, когда он вызывался «не -интерактивно».
Чтобы обойти тот факт, что не -интерактивная оболочка не запускает ни /etc/profile
, ни /etc/bashrc
, я создал специальный сценарий оболочки в /etc/profile.d/
, например. «пользовательский _shopts.sh» только с параметрами shopt, которые я хотел бы иметь для каждой сессии, и в этом же скрипте я экспортирую переменнуюBASH_ENV=/etc/profile.d/custom_shopts.sh
Таким образом, в любой оболочке, которую я запускаю (оболочка входа в систему, интерактивная оболочка или не -интерактивная оболочка, но за исключением bash --posix
), сценарий оболочки /etc/profile.d/custom_shopt.sh
запускается и устанавливает параметры магазина. Я ожидаю.
Как указал Джефф, будет проще создать отсортированный массив, как в:
set -A files $(ls -trd -- ~/a ~/b ~/c)
Здесь вывод ls
разделен на $IFS
символ (, по умолчанию содержащий SPC, TAB, LF и NUL ). Чтобы разделить только LF (, чтобы иметь возможность работать с именами файлов, которые содержат символы SPC или TAB (, но явно не LF )), вы можете установить IFS=$'\n'
или использовать флаг расширения параметра f
:
files=(${(f)"$(ls -trd -- $files)"})
(здесь также используется синтаксис стиля zsh -array=(...)
вместо стиля ksh88 -set -A array...
, поскольку этот синтаксис в любом случае уже специфичен для zsh -).
Будет намного проще отсортировать список при его построении . Но если не можешь…
Классический подход состоит в том, чтобы добавить критерий сортировки к данным, затем отсортировать их, а затем удалить добавленный мусор. Создайте массив, содержащий временные метки и имена файлов, таким образом, чтобы это было однозначно и с временными метками в формате, который можно отсортировать лексикографически. Отсортируйте массив (, используя флаг раскрытия параметраo
), затем удалите префикс. Вы можете использовать модульstat
для получения времени модификации файла.
zmodload zsh/stat
for ((i=1; i<$#files; i++)); do times[$i]=$(stat -g -F %020s%N +mtime -L -- $files[$i]):$files[$i]; done
sorted=(${${(o)times}#*:})
Формат %N
для zstat (для получения меток времени с наносекундным разрешением )требует zsh ≥5,6. Если ваш zsh старше, удалите его, и код все равно будет работать, но сравнивая метки времени с разрешением 1 -секунды. Многие файловые системы имеют разрешение в доли секунды, но я не думаю, что вы можете получить его с помощью модуля zsh stat
в более старых версиях zsh.
Если ваш zsh слишком старый, вы можете получить более точные метки времени с помощью утилиты stat
из GNU coreutils . Если он у вас есть, у вас, вероятно, есть и другие основные утилиты GNU, поэтому я буду использовать их. Утилиты GNU coreutils обычно присутствуют во встроенных Linux, отличных от -, но могут отсутствовать в BSD или macOS. В macOS их можно установить с помощью brew
. Если основные утилиты GNU не являются частью базовой операционной системы, вам может потребоваться изменить stat
на gstat
, sort
на gsort
и cut
на gcut
.
if (($#files)); then
sorted=(${(0@)"$(stat --printf='%040.18Y:%n\0' "$files[@]" | sort -rz | cut -z -d':' -f2-)"})
else
sorted=()
fi
Альтернативный подход zsh заключается в создании шаблона, включающего все файлы из $files
и другие. Отсортируйте файлы, соответствующие этому шаблону, а затем отфильтруйте их, чтобы включить только нужные файлы. Вам нужно построить весь шаблон для more_files
, что не всегда практично.
more_files=(~/*(Om))
sorted=(${more_files:*files})
Вы можете использовать подход, аналогичный этому:
zmodload zsh/stat
array=(file1 file2...)
# store mtimes in an associative array:
typeset -A mtime
stat -nLF %s.%N -A mtime +mtime -- $array
# sort using the Oe glob qualifier
sorted_array=(/(e['reply=($array)']nOe['REPLY=$mtime[$REPLY]'])
(%N
для наносекунд требуется zsh 5.6 или новее ).