Bash: подчиненное поведение ls
Мне интересно, почему я не получаю такой же вывод от:
ls -1 -tF | head -n 1
а также
echo $(ls -1 -tF | head -n 1)
Я пытался получить последний измененный файл, но используя его внутри вложенной оболочки, иногда я получаю более одного файла в результате?
Почему этого и как избежать?
2 ответа
Проблема возникает из-за того, что вы используете нецитированную подоболочку и -F
флаг для ls выводит специальные символы оболочки, добавляемые к именам файлов.
-F, --classify
добавить индикатор (один из */=>@|) в записи
К исполняемым файлам добавляется *.
Когда ты бежишь
echo $(ls -1 -tF | head -n 1)
затем
$(ls -1 -tF | head -n 1)
вернет имя файла, и если это будет исполняемый файл, а также будет префиксом для другого файла, то он вернет оба.
Например, если у вас есть
test.sh
test.sh.backup
тогда он вернется
test.sh*
который при отражении расширяется до
test.sh test.sh.backup
Цитирование подоболочки предотвращает это расширение
echo "$(ls -1 -tF | head -n 1)"
возвращается
test.sh*
Я только что нашел ошибку: если вы используете echo $(ls -1 -tF | head -n 1)
механизм перетаскивания файлов может привести к дополнительным совпадениям.
Так echo "$(ls -1 -tF | head -n 1)"
бы избежать этого.
Потому что, если результатом является исполняемый файл, он содержит * в конце.
Я попытался поместить причину -F в комментарии, но теперь я решил поместить это здесь:
Я добавил следующие строки в мой.bashrc, чтобы иметь ярлык для отображения последних измененных файлов или каталогов:
function L {
myvar=$1; h=${myvar:="1"};
echo "last ${h} modified file(s):";
export L=$(ls -1 -tF|fgrep -v / |head -n ${h}| sed 's/\(\*\|=\|@\)$//g' );
ls -l $L;
}
function LD {
myvar=$1;
h=${myvar:="1"};
echo "last ${h} modified directories:";
export LD=$(ls -1 -tF|fgrep / |head -n $h | sed 's/\(\*\|=\|@\)$//g'); ls -ld $LD;
}
alias ol='L; xdg-open $L'
alias cdl='LD; cd $LD'
Так что теперь я могу использовать L (или L 5), чтобы перечислить последние (последние 5) измененные файлы. Но не каталоги.
И с L; jmacs $L I Я могу открыть мой редактор, чтобы отредактировать его. Традиционно я использовал свой псевдоним lt='ls -lrt', но потом мне пришлось набрать имя заново...
Теперь после mkdir ... я использую cdl для перехода на этот каталог.