Список всех файлов / двоичных файлов в текущем PATH


10

Есть ли «простой» способ запуска команды в стиле «ls -la» для вывода списка всех файлов / исполняемых файлов в текущем PATH?

(Я намереваюсь направить вывод в grep для поиска команд с неизвестными префиксами, но в основном с известными «именами», тот случай, когда автозаполнение / табуляция в bash практически бесполезны. Так что это своего рода «обратный авто полная функция "...)


Можете привести примеры? Чем он будет отличаться ls -la?
Джон Сиу

"ls -la" / "ls -a" отображает только файлы в вашем текущем каталоге (pwd). Я хочу перечислить все (исполняемые) файлы во всех каталогах, включенных в PATH.
SME

Ответы:


19
compgen -c # will list all the commands you could run.
compgen -a # will list all the aliases you could run.
compgen -b # will list all the built-ins you could run.
compgen -k # will list all the keywords you could run.
compgen -A function # will list all the functions you could run.
compgen -A function -abck # will list all the above in one go. 

Хорошо, это очень много, что я искал. Он даже включает исполняемые двоичные файлы в текущем каталоге. Спасибо.
См

Хорошо работает ... в Bash.
Эмануэль Берг

Есть ли способ перечислить путь каждого из них, не делая which $(compgen -A function -abck)?
h3rrmiller

Я не мог найти лучшую альтернативу.
Nykakin

3

Вот функция, которая перечисляет содержимое каталогов $PATH. Если переданы аргументы, функция перечисляет только те команды, имя которых содержит один из аргументов. Аргументы интерпретируются как шаблоны глобуса.

shopt -s extglob
lspath () {
  local IFS pattern
  IFS='|'
  pattern="*@($*)*"
  IFS=':'
  for d in $PATH; do
    for x in "$d/"$pattern; do
      [ "$x" = "$d/$pattern" ] || echo "${x##*/}"
    done
  done | sort -u
}

Как и многие вещи, это проще в Zsh.

lspath () {
  (($#)) || set ''
  print -lr -- $^path/*$^@*(N:t) | sort -u
}

Символ ^в раскрытии параметра вызывает добавление текста, объединенного с массивом, к каждому элементу массива, например, к path=(/bin /usr/bin); echo $^path/fooотпечаткам /bin/foo /usr/bin/foo.
/*$^@*выглядит как оскорбление комиксов, но на самом деле это обычный символ /, подстановочный знак *, специальный параметр $@(массив позиционных параметров) с ^модификатором и снова *.
(N:t)является префиксом glob N для получения пустого раскрытия, если нет совпадения, за которым следует модификатор history, t чтобы сохранить только базовое имя («tail») для каждого совпадения.

Более загадочный, избегает внешнего звонка, но это только косметический интерес:

lspath () {
  (($#)) || set ''
  local names; names=($^path/*$^@*(N:t))
  print -lr -- ${(ou)names}
}

На самом деле вы можете искать aproposкоманду, которая ищет справочные страницы команд, краткое описание которых содержит ключевое слово. Ограничение состоит в том, что это находит только те команды, которые имеют справочную страницу.


В функции zsh второе, ^похоже, не приводит к выводу для вызова «без аргументов»? Если вы уроните его, вы можете перечислить их все и по-прежнему искать отдельные ключевые слова (но не список из них). (Non:t)Кажется, что звездочки следует расширить? Не могу понять, что последний.
Эмануэль Берг

@EmanuelBerg Правильно, спасибо за исправление. Я добавил объяснение шума линии.
Жиль "ТАК - перестань быть злым"

Хорошо, давайте посмотрим: если нет аргументов, вы устанавливаете «их» в ничто, потому что то, что было (когда их не было), все еще каким-то образом мешало тому, что вы сделали дальше? Кроме того, я никогда не видел строчных букв path, но когда я запускаю его в оболочке, это действительно $ PATH, но с пробелами вместо :. Остальное кристально ясно :)
Эмануэль Берг

@EmanuelBerg Нет: если аргументов нет, я устанавливаю массив аргументов как массив из одного элемента, содержащий пустую строку. Таким образом, без аргументов означает, что каждое имя, содержащее пустую строку, соответствует, то есть каждое имя соответствует. $pathэто функция zsh: это связанный параметр , массив, который автоматически обновляется при PATHобновлении и наоборот.
Жиль "ТАК - перестань быть злым"

Ага, теперь вижу! Вау, это было неортодоксально!
Эмануэль Берг

1
function findinpath () { 
   OLDIFS="$IFS" ; 
   IFS="$(printf ':\t\n')" ; 
   for regexp in "$@" ; do 
      for adir in $PATH ; do 
         find "$adir" -perm -111 -a ! -type d -ls 2>/dev/null | grep -i "/[^/]*$regexp"
      done ; 
   done ; 
   IFS="$OLDIFS" ; 
}

поиск только соответствует тому, что: установлен хотя бы один бит "x" (исполняемый), и это не каталог.

и используйте его со списком регулярных выражений:

findinpath awk sed '\.sh$'

регулярное выражение "." покажет вам все
Оливье Дюлак

с помощью обычного IFS вы можете найти повторяющиеся записи в вашем $ PATH с:echo $PATH | tr ':' '\n' | sort | uniq -d
Olivier Dulac

1
Я попробовал код для всех ответов, и это единственный, который фактически дал мне то, что я искал (полные пути к каждому экземпляру данной команды в PATH).
Крис Пейдж

Я рад, что это помогло :)
Оливье Дюлак

1
for i in $(echo $PATH | sed -e 's/\:/\ /g'); do find "$i" -perm +rwx -exec echo {} \; 2> /dev/null; done

сначала мы повторяем $PATHв sed и заменяем ":" на "".

затем мы делаем поиск по каждой из этих вещей, чтобы найти файлы с помощью rwx и повторить их.

2> /dev/nullэто так findне будет печатать ошибки


3
вам нужно -maxdepth 1и -type fв вашей находке, иначе вы найдете подкаталоги и их файлы (что поиск PATH не будет). Кроме того, ваш тест на разрешение странный - +xя думаю, просто
Дероберт

Это не будет обрабатывать крайние случаи, когда допустимая пустая запись совпадает с '.', Например :/binили /bin::/usr/bin. Попробуйте добавить s/::/:.:/;s/^:/.:/;s/:$/:./в sedкоманду.
Arcege

На самом деле findможно искать больше путей, так что вы можете делать это без цикла: find $(echo $PATH | sed -e 's/\:/\ /g') -perm +rwx …Конечно, имена каталогов, содержащие пробелы, испортят это, но в любом случае на основе цикла есть такая же проблема.
manatwork

@ manatwork ты прав. Я добавил цитаты, чтобы решить эту проблему только сейчас
h3rrmiller

Извините, это ничего не решает. Проблема заключается в замене двоеточий пробелами для разделения слов. Таким образом, вы преобразуете «/ foo bar: / fiz baz» в «/ foo bar / fiz baz», а затем передаете это for. Так forчто перебираем список из 4 слов. Для того, чтобы манипулировать словом Расщепление лучше установить в IFSсоответствии с вашими потребностями: IFS=':'; find $PATH -perm +rwx ….
manatwork
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.