Как возвратить каталог данного исполняемого файла?

Существует отчет об ошибках по этой проблеме в системе отслеживания ошибок Debian, упоминая, что нестабильные репозитории Debian уже зафиксировали пакеты (и базы данных пакета показывает, что они уже поражают Debian/testing repos). Так как Crunchbang 10 "Statler" основан на Debian/stable, эти фиксированные пакеты могли занять время, чтобы быть доступными там; Вы можете однако смешивание и подгонка, если Вы немного осторожны (см., например, этот вопрос).

4
01.08.2013, 17:44
5 ответов
executable=mysql

executable_path=$(command -v -- "$executable") &&
  dirname -- "$executable_path"

(не используйте which).

Конечно, это не будет работать если $executable встроенная оболочка, функция или псевдоним. Я не знаю ни о какой оболочке где mysql встроенное. Это не будет функцией или исказит, если Вы не определили их ранее, но затем необходимо знать об этом. Исключение к этому могло быть bash который поддерживает экспортируемые функции.

$ bash -c 'command -v mysql'
/usr/bin/mysql
$ mysql='() { echo test;}' bash -c 'command -v mysql'
mysql
7
27.01.2020, 20:47
  • 1
    +1, но это было бы еще лучшим IMO с коротким объяснением того, почему не нужно использовать which. –  a CVn 01.08.2013, 18:04
  • 2
    @MichaelKjörling - Я попытался объяснить почему which плохо в моем ответе.Сообщите мне, что Вы об этом думаете. –  slm♦ 01.08.2013, 18:47
  • 3
    @slm! +1 Вам также. –  a CVn 01.08.2013, 21:03
  • 4
    Был бы это, это было настолько просто! Иногда это печатает .. (Поскольку существует псевдоним, который which не знает.) Zsh имеет очень удобное =mysql синтаксис, но к сожалению это не складывает с ${…##*/} или …:h. –  Gilles 'SO- stop being evil' 02.08.2013, 02:59
  • 5
    @Gilles, можно сделать ${${:-mysql}:c:h} все же. ksh и zsh имеют whence -p к обратным каналам команд, даже если существует встроенное/искажать/функциональное для него, но затем это не могло бы быть тем, что Вы хотите, поскольку это не то, что вызвала бы оболочка. –  Stéphane Chazelas 02.08.2013, 09:59

который

В целом этой команды нужно избежать.

Почему?

Поскольку это использует Вашу текущую среду при построении $PATH то, что это собирается оценить при поиске исполняемых файлов. Это может привести к беспорядку при контакте со сценариями оболочки и таким, который будет потенциально использовать $PATH как создано Вашим ~/.bashrc и ~/.bash_profile файлы при выполнении.

Например:

# path to start
$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/sam/bin

# let's change it
$ export PATH=/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin

$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin

# simulate a new env. for a shell script
$ bash -lc "echo \$PATH"
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/sam/bin

Заметьте, что сценарий оболочки, если выполняется имел бы исходную среду, не текущую!

ввести

Можно также использовать команду type определять местоположение исполняемых файлов в Вашей среде:

$ type ls
ls is aliased to `ls --color=auto'

Или видеть все, используйте -a переключатель:

$ type -a ls
ls is aliased to `ls --color=auto'
ls is /bin/ls

type покажет, что Вы искажаете, а также местоположение. Для нахождения каталога, хотя, @StephaneChazelas решение использования command является лучшим.

whereis

Можно также использовать команду whereis но это не использует Вашу среду, она имеет hardcoded набор каталогов, что она заглядывает. Посмотрите человека whereis для получения дополнительной информации.

расположиться

Этот мог бы смутить людей, но некоторые дистрибутивы включают инструмент, который работает от задания крона, обычно ежедневно, который сканирует весь диск и создает немного файла базы данных, который можно затем искать использование locate команда.

  • Задание крона называют /etc/cron.daily/mlocate.cron в моей системе Fedora 14.
  • Инструмент, делающий сканирование, называют /usr/bin/updatedb.
  • Файл DB расположен здесь: /var/lib/mlocate/mlocate.db.

Используя то, что я рассмотрел бы определенным взломом, который можно подключить коаксиальным кабелем locate только искать файлы, которые называют ls следующим образом:

$ locate -b '\ls'
/bin/ls
/usr/share/javadoc/java-1.6.0-openjdk/api/org/w3c/dom/ls
/usr/share/javadoc/java-1.6.0-openjdk/jre/api/plugin/dom/org/w3c/dom/ls
/usr/share/locale/l10n/ls
/var/cache/abrt-di/usr/src/debug/gcc-4.5.1-20100924/libjava/classpath/external/w3c_dom/org/w3c/dom/ls
/var/cache/abrt-di/usr/src/debug/gcc-4.5.1-20100924/libjava/classpath/gnu/xml/dom/ls

Вышеупомянутые работы, потому что Вы \ globbing символ, таким образом, это отключает неявную замену ls с *ls*.

См. определять местоположение страницу справочника для получения дополнительной информации.

whatis

Менее известный инструмент называют whatis. Этот подобен locate, таким образом, это поддерживается DB. Это полезно для обнаружения команд однако:

$ whatis ls
ls                   (1)  - list directory contents
ls                   (1p)  - list directory contents

Инструмент вызывается от задания крона, /etc/cron.daily/makewhatis.cron. Однако makewhatis создает его базу данных из man страницы в Вашей системе.

Вы видите больше об этом в makewhatis страницах справочника.

Просто имя каталога?

Можно использовать команду dirpath против любого вывода, произведенного командами, я упомянул выше для получения просто компонента каталога.

dirpath не делает никакой проверки, таким образом, можно дать ему примерно любой тип пути к файлу, и это даст Вам часть каталога:

$ dirname /some/path/to/a/script
/some/path/to/a
4
27.01.2020, 20:47
  • 1
    я не понимаю Ваш первый раздел о "почему не использование который". Я создал отдельный вопрос для него, поскольку у нас должен быть канонический здесь. Не стесняйтесь добавлять свой ответ там. –  Stéphane Chazelas 02.08.2013, 02:03
  • 2
    @StephaneChazelas - сделает. Не видел это прежде. Вы предлагаете весь ответ или просто тот раздел? Также я скопировать/вставить или перемещаю его так или иначе? –  slm♦ 02.08.2013, 02:07
  • 3
    @StephaneChazelas - просто видел Ваши Вопросы и ответы. Представьте 8-). –  slm♦ 02.08.2013, 02:39

Его довольно простое с xargs:

which mysql | xargs dirname
1
27.01.2020, 20:47

dirname является самым простым способом достигнуть этого:

$ which mysql
/usr/bin/mysql
$ dirname `which mysql`
/usr/bin
0
27.01.2020, 20:47

Как другие объяснили, не использовать which.

Можно записать немного функции оболочки, которая выполняет итерации по PATH переменная.

which-directory () (
  IFS=:
  set -g
  for d in $PATH; do
    if [ -z "$d" ]; then d=.; fi
    if [ -x "$d/$1" ]; then printf '%s\n' "$d"; return; fi
  done
  return 1
)

С другой стороны, можно звонить command -v. Это сообщает о псевдонимах и функциях, а также внешних командах. В случае, если у Вас есть псевдоним или функция mysql это называет внешнюю команду того же имени с дополнительными параметрами, можно звонить command -v в недавно запущенной оболочке, которая не имеет никаких функций или искажает определенный. Обратите внимание, что это делает правильную вещь только если псевдоним или вызовы функции внешняя команда того же имени. Следующие две остроты эквивалентны (предположение, что у Вас нет каталога или имени исполняемого файла на Вашем ПУТИ, содержащем новую строку).

dirname -- "$(sh -c 'command -v "$0"' -- mysql)"
sh -c 'command -v "$0"' -- mysql | sed -e 's!.*/!!'

В zsh эта острота делает то же самое:

echo =mysql(:h)
0
27.01.2020, 20:47

Теги

Похожие вопросы