Почему ваша функция не работает
Есть несколько причин:
- Я предполагаю, что
echo - это артефакт, используемый для проверки синтаксиса или около того. Нет смысла, если вы хотите, чтобы функция делала то, что вы описали.
- Прописная
HEAD . В Linux это должно быть head . Я не уверен насчет других ОС, где вы можете запустить bash и head . HEAD может работать или не работать в некоторых из них, но head должна работать везде.
- Разбор
ls не рекомендуется. Об этом есть статья . Главное в вашем случае будет то, что ls не может надежно печатать имена, включая специальные или непечатные символы.
- Там нет никакой логики , чтобы проверить только каталоги, вы можете в конечном итоге пытается
cd в файл , когда нет каталога.
- Нет логики обрабатывать ситуацию, когда текущий рабочий каталог пуст.
Все эти проблемы могут быть отлажены, кроме этой ls . Это недостаток дизайна. Если вы думаете , ls ограничения не укусят вас , то вы можете пойти с решением от этого другого ответа .
Для выполнения некоторых тестов вы можете создать проблемный каталог с помощью mkdir "$(echo -ne "foo\nbar")" ; ls -О решение, вероятно , не в состоянии, если это каталог cdrc должны cd в. Чтобы удалить проблемный каталог, вызовите rmdir "$(echo -ne "foo\nbar")" .
Мне удалось создать более безопасную функцию.
Решение
function cdrc { cd "$(find -maxdepth 1 -mindepth 1 -type d -exec stat --printf "%Y %n\0" {} + | sort -znr | head -zn 1 | cut -f 2- -d " ")" ;}
объяснение
Чтобы объяснить мою функцию, я напишу это более четко. Обратите внимание, \ в самом конце строки говорит bash что команда продолжается на следующей строке; поэтому мой код ниже рассматривается как однострочный, его можно вставить целиком в интерактивный bash .
function cdrc { \
cd "$( \
find -maxdepth 1 -mindepth 1 -type d -exec \
stat --printf "%Y %n\0" {} + |
sort -znr |
head -zn 1 |
cut -f 2- -d " " \
)" \
;}
Процедура выглядит следующим образом:
- Сначала
find запускается. Он не спускается в подкаталоги (-maxdepth 1), он также не находит текущий каталог (-mindepth 1). Он находит только каталоги (-type d). Затем запускается команда stat (спасибо -exec):
stat печатает время последней модификации данных (%Y , mtime, секунд с начала эпохи), один пробел и имя (%n). Благодаря опции --printf он не добавляет символ новой строки, но интерпретирует \0 как нулевой символ, который должен быть добавлен в конце каждой строки.
{} является частью синтаксиса find -exec . Во время выполнения find он заменяется именем каталога, поэтому stat знает, какова его цель.
+ также является частью синтаксиса find -exec . Это заставляет find передавать несколько имен одному stat (и stat может с этим справиться). Таким образом, создается меньше процессов stat , это быстрее.
На данный момент у нас ноль или более строк. Они выглядят примерно так:
1493488341 directory name
1497365306 troublesome?directory name
но они заканчиваются нулем, поэтому даже если есть имена с проблемными символами, они будут обработаны правильно. В первом столбце есть mtimes без начальных пробелов (я проверил поведение stat с числами различной длины, чтобы убедиться), затем первый пробел отделяет mtime от имени каталога.
- Этот вывод обрабатывается в дальнейшем:
sort сортирует строки по числовому значению (-n), использует обратный порядок (-r) и работает со строками с нулевым символом в конце (-z). Таким образом, каталог, который нам нужен, теперь находится в первой строке.
- Затем
head покидает только первую строку (-n 1); также сказано, что нужно работать со строками с нулевым символом в конце (-z).
cut обрезает строку, обрабатывая пробел как разделитель (-d " ") и оставляя второе поле и все, что следует за (-f 2-), т.е. все после первого пробела. Работает со строками с нулевым символом в конце (-z). Окончательный вывод - это желаемое имя каталога.
Обратите внимание, что вывод будет пустым, если в текущем рабочем каталоге нет каталога.
$(…) Заменяется выводом всего, что находится внутри. На данный момент у нас есть либо cd "some directory name" либо cd "" . Первая команда делает то, что вы хотите; последний (когда нет каталога) ничего не делает.
Функция потерпит неудачу, если каталог, в который она должна cd будет (пере) перемещен / переименован после того, как find найдет его. Кроме того, stat может выдавать ошибки, если какой-либо каталог перемещается / переименовывается, когда функция работает.