Чтобы иметь дело с произвольными именами файлов (включая те, которые содержат символы новой строки), обычный трюк заключается в поиске файлов внутри . //.
вместо .
. Поскольку //
обычно не может возникнуть при обходе дерева каталогов, вы уверены, что //
сигнализирует о начале нового имени файла в find
(или здесь lsattr -R
) вывод.
lsattr -R .//. | awk '
function process() {
i = index(record, " ")
if (i && index(substr(record,1,i), "i"))
print substr(record, i+4)
}
{
if (/\/\//) {
process()
record=$0
} else {
record = record "\n" $0
}
}
END{process()}'
Обратите внимание, что вывод по-прежнему будет разделен новой строкой. Если вам нужно его обработать, вам придется его адаптировать. Например, вы можете добавить -v ORS = '\ 0'
, чтобы передать его в GNU xargs -r0
.
Также обратите внимание, что lsattr -R
(по крайней мере 1.42.13) не может сообщать флаги файлов, путь которых больше, чем PATH_MAX (обычно 4096), поэтому кто-то может скрыть такой неизменяемый файл, переместив его родительский каталог (или любой из компонентов пути, которые к нему ведут, кроме самого себя, поскольку он неизменяемый) в очень глубокий каталог.
Чтобы обойти эту проблему, можно использовать find
с -execdir
:
find . -execdir sh -c '
a=$(lsattr -d "$1") &&
case ${a%% *} in
(*i*) ;;
(*) false
esac' sh {} \; -print0
Теперь, с -print0
, это можно обработать постобработку, но если вы собираетесь делать что-либо с этими путями, обратите внимание, что любой системный вызов на пути к файлам, больший, чем PATH_MAX , все равно завершится ошибкой, и компоненты каталога могут быть переименованы в интервале.
Если мы хотим получить надежный отчет о дереве каталогов, которое потенциально может быть записано другими, есть еще несколько проблем, присущих самой команде lsattr
, которые мы должны упомянуть:
lsattr -R.
просматривает дерево каталогов, это зависит от состояния гонки. Можно заставить его спускаться в каталоги за пределами дерева каталогов, маршрутизируемых по адресу .
путем замены некоторых каталогов символическими ссылками в нужный момент. lsattr -d файл
имеет состояние гонки. Эти атрибуты применимы только к обычным файлам или каталогам.Итак, lsattr
сначала выполняет lstat ()
, чтобы проверить правильность типа файла, а затем выполняет open ()
, а затем ioctl ()
для получения атрибутов. Но он вызывает open ()
без O_NOFOLLOW
(или O_NOCTTY). Кто-то может заменить файл
символической ссылкой на / dev / watchdog
, например, между lstat ()
и open ()
и вызвать систему перезагрузить. Он должен выполнить open (O_PATH | O_NOFOLLOW)
, за которым следует fstat ()
, openat ()
и ioctl ()
, чтобы избежать условия гонки. Описанное вами поведение является ожидаемым. Переменные среды определены в .profile
, которые считываются при входе в систему. Запуск нового сеанса tmux не приводит к входу в систему. Tmux по умолчанию запускает оболочку входа в систему, но вы отключили ее в конфигурации, поэтому Окна tmux просто наследуют внешнюю среду.
Если вы поместите source.profile
в свой .zshrc
, это переопределит любую среду, в которой работает оболочка. Это означает, что вы не можете запускать оболочку в среде, отличной от среды по умолчанию, например. попробовать что-то с другим PATH
.
Просто удалите source.profile
из .zshrc
. У вас будет среда по умолчанию, установленная во время входа в систему во всех оболочках.
Если ваша оболочка для входа в систему — zsh, обратите внимание, что во время входа в систему она читает .zprofile
, а не .profile
. Это отличается от bash, который читается как .profile
, если .bash_profile
отсутствует. Zsh работает по-другому, потому что его синтаксис отличается от sh, поэтому он не может читать .profile
напрямую. Если вы хотите иметь .profile
, который работает под sh для входа в систему с графическим интерфейсом, а также использовать тот же файл для входа в текстовый режим,и вы установили zsh в качестве оболочки входа в систему, затем используйте следующую строку в качестве~/.zprofile
:
emulate sh -c 'source ~/.profile'
Если tmux настроен на запуск оболочки входа в систему, то все окна tmux будут переопределять окружающую среду, а не наследовать ее. Это означает, что если вы определяете новые переменные вне tmux, они все равно будут в сеансе tmux, но если вы измените значения уже определенных переменных, ваши изменения будут потеряны внутри tmux. В общем, поведение tmux по умолчанию не имеет особого смысла. Избежать этого — точка линии set-option -g default-command $SHELL
в ~/.tmux.conf
.
Если вы используете tmux для «нового входа в систему», вы можете предпочесть, чтобы каждое окно запускалось в новой среде. Если это так, то вам, вероятно, следует очистить свою среду с помощью чего-то вроде
set-option -g default-command env -i USER="$USER" LOGNAME="$LOGNAME" $SHELL
И помните, что если ваша оболочка для входа в систему — zsh, она читается как .zprofile
, а не .profile
.