Bash скрипт расширение файла

Обновлено: 05.07.2024

Как получить путь к каталогу, в котором Баш сценарий находится, внутри этот скрипт?

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

является полезным однострочным, который даст вам полное имя каталога скрипта независимо от того, откуда он вызывается.

он будет работать до тех пор, пока последний компонент пути, используемый для поиска скрипта, не является символической ссылкой (ссылки каталога в порядке). Если вы также хотите разрешить любые ссылки на сам скрипт, вам нужно многострочное решение:

этот последний будет работать с любой комбинацией псевдонимы, source , bash -c , симлинки, так далее.

остерегайтесь: если вы cd в другой каталог перед запуском этого фрагмента, результат может быть неправильным! Кроме того, следите за $CDPATH gotchas.

чтобы понять, как это работает, попробуйте запустить этот более подробном виде:

и он напечатает что-то вроде:

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

команда dirname является самой простой, просто разбирая путь до имени файла с переменной $0 (имя скрипта):

, а как Мэтт б указал, возвращаемый путь отличается в зависимости от того, как вызывается скрипт. pwd не выполняет эту работу, потому что это говорит вам только о текущем каталоге, а не о том, в каком каталоге находится скрипт. Кроме того, если выполняется символическая ссылка на скрипт ,вы получите (возможно, относительную) путь к тому, где находится ссылка, а не фактический скрипт.

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

readlink разрешит путь скрипта к абсолютному пути от корня файловой системы. Таким образом, любые пути, содержащие одиночные или двойные точки, Тильды и/или символические ссылки, будут разрешены до полного пути.

вот сценарий, демонстрирующий каждый из них, whatdir.sh:

запуск этого скрипта в моем домашнем каталоге, используя относительный путь:

снова, но используя полный путь к скрипту:

теперь изменение каталогов:

и, наконец, используя символическую ссылку, чтобы выполнить скрипт:

работает для всех версий,в том числе

  • при вызове через мягкую ссылку multple depth,
  • когда файл
  • когда скрипт вызывается командой " source " ака . (точка) оператор.
  • когда arg изменяется от абонента.
  • "./script"
  • "/full/path/to/script"
  • "/some/path/../../another/path/script"
  • "./some/folder/script"

альтернативно, если сценарий bash сам относительная ссылка вы хочу чтобы следовать за ним и вернуть полный путь связанного скрипта:

SCRIPT_PATH дается в полном пути, независимо от того, как он называется.
Просто убедитесь, что вы нашли это в начале сценария.

вы можете использовать $BASH_SOURCE

Это должно сделать это:

работает с символическими ссылками и пробелами в path. Видеть страницах dirname и более ранних версий.

из комментария, похоже, не работает с Mac OS. Понятия не имею почему. Есть предложения?

pwd можно использовать для поиска текущего рабочего каталога и dirname найти каталог конкретного файла (команда, которая была запущена, составляет , так что dirname должен дать вам каталог текущего скрипта).

, dirname дает точно часть каталога имени файла, которая, скорее всего, будет относительно текущего рабочего каталога. Если вашему скрипту по какой-то причине нужно изменить каталог, то вывод из dirname становиться бессмысленным.

Я предлагаю следующее:

таким образом, вы получите абсолютный, а не относительный путь.

поскольку скрипт будет запущен в отдельном экземпляре bash, нет необходимости восстанавливать рабочий каталог после этого, но если вы по какой-то причине хотите вернуться в свой скрипт, вы можете легко назначить значение pwd в переменную перед изменением каталога для дальнейшего использования.

решает конкретный сценарий в вопросе, я считаю, что абсолютный путь более полезен в целом.

Я не думаю, что это так просто, как другие сделали это. pwd не работает, так как текущий каталог не обязательно является каталогом со скриптом. $0 также не всегда имеет информацию. Рассмотрим следующие три способа вызова скрипта.

в первом и третьем способах $0 не имеет полной информации о пути. Во втором и третьем pwd не работают. Единственный способ получить dir третьим способом - это запустить путь и найти файл с правильное совпадение. В основном код должен был бы переделать то, что делает ОС.

один из способов сделать то, что вы просите, - это просто жестко закодировать данные в каталоге /usr/share и ссылаться на него полным путем. В любом случае данные не должны быть в каталоге /usr/bin, так что это, вероятно, то, что нужно сделать.

это получает текущий рабочий каталог на Mac OS X 10.6.6:

это специально для Linux, но вы можете использовать:

вот POSIX совместимый однострочный:

Я пробовал каждый из них, и ни один из них не работал. Один был очень близко, но имел крошечный жучок, который сломал его плохо; они забыли обернуть путь в кавычки.

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

попробуйте этот каталог для размера:

/ var / No one / Thought/About Spaces Being/in a Directory/Name / и вот ваш файл.текст

это получает правильно, независимо от того, как и где вы его запускаете.

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

надеюсь, что это поможет

Я бы использовал что-то вроде этого:

небольшое изменение решения e-satis и 3bcdnlklvc04a указано в ответ

Это должно работать во всех случаях, которые они перечислили.

EDIT: предотвращение popd после неудачного pushd, благодаря konsolebox

вот простой, правильный путь:

$ - полный путь к скрипту. Значение этого будет правильным даже тогда, когда скрипт находится в исходном состоянии, например source <(echo 'echo ') печать Баш, при замене его на $ будет напечатан полный путь к скрипту. (Конечно, это предполагает, что вы в порядке, принимая зависимость от Bash.)

readlink -f - Рекурсивно разрешает любые символические ссылки в указанном пути. Это расширение GNU и недоступно (например) в системах BSD. Если вы используете Mac, вы можете использовать Homebrew для установки GNU coreutils и замените это на greadlink -f .

и конечно dirname получает родительский каталог путь.

$_ стоит упомянуть в качестве альтернативы $0. Если вы запускаете скрипт из bash, принятый ответ может быть сокращен до:

обратите внимание, что это должен быть первый оператор в вашем скрипте.

  • абсолютные пути или относительные пути
  • файл и каталог ссылок
  • вызов как script , bash script , bash -c script , source script или . script
  • пробелы, вкладки, новые строки, unicode и т. д. в каталогах и/или именем
  • имена файлов, начинающиеся с дефиса

если вы работаете с Linux, кажется, что с помощью proc handle-лучшее решение для поиска полностью разрешенного источника текущего запущенного скрипта (в интерактивном сеансе ссылка указывает на соответствующий /dev/pts/X ):

в этом есть немного уродства, но исправление компактно и легко понять. Мы не используем только примитивы bash, но я в порядке с этим потому что readlink значительно упрощает задачу. The echo X добавляет X до конца строки переменной, так что любые конечные пробелы в имени файла не съедаются, а подстановка параметров $ в конце строки избавляется от X . Потому что readlink добавляет свою собственную новую строку (которая обычно была бы съедена в замене команды, если бы не наш предыдущий обман), мы должны избавиться от этого тоже. Это легче всего сделать с помощью $'' схема цитирования, которая позволяет использовать escape-последовательности, такие как \n для представления новых строк (это также, как вы можете легко сделать хитро именованные каталоги и файлы).

выше должно охватывать ваши потребности в поиске текущего сценария на Linux, но если у вас нет proc файловая система в вашем распоряжении, или если вы пытаетесь найти полностью разрешенный путь к какому-либо другому файлу, возможно, вы найдете приведенный ниже код полезным. Это только небольшая модификация от выше один-лайнер. Если вы играете со странным каталогом / именами файлов, проверьте вывод с помощью обоих ls и readlink информативно, как ls выведет "упрощенные" пути, подставляя ? для таких вещей, как newlines.

Я пишу ночную сборку script в bash.
Все нормально и денди, за исключением одной маленькой хватки:

Моя проблема заключается в определении расширения файла и последующем действии. Я знаю, что проблема заключается в if-statement, тестировании для txt файла.

Как определить, имеет ли файл суффикс .txt?

Я думаю, вы хотите сказать: "Являются ли последние четыре символа $файла равными .txt ?" Если это так, вы можете использовать следующее:

Обратите внимание, что требуется пробел между file: и -4 , так как модификатор ': -' означает что-то другое.

То есть, двойные скобки и кавычки.

Правая сторона == - это шаблон оболочки. Если вам нужно регулярное выражение, используйте =

Вы просто не можете быть уверены в системе Unix, что файл .txt действительно является текстовым файлом. Лучше всего использовать "файл". Возможно, попробуйте использовать:

Затем вы можете использовать список типов MIME для сопоставления или анализа первой части MIME, где вы получаете такие вещи, как "текст", "приложение" и т.д.

Вы можете использовать команду "файл", если вы действительно хотите узнать информацию о файле, а не полагаться на расширения.

Если вам удобно пользоваться расширением, вы можете использовать grep, чтобы увидеть, совпадает ли он.

Вы также можете сделать:

Подобно "файлу", используйте немного более простой "mimetype -b", который будет работать независимо от расширения файла.

Изменить: вам может потребоваться установить libfile-mimeinfo-perl в вашей системе, если mimetype недоступен

Я написал bash script, который смотрит на тип файла, затем копирует его в место, я использую его для просмотра видео, которое я просматривал в Интернете из моего кеша firefox:

Он использует похожие идеи для тех, которые представлены здесь, надеюсь, что это кому-то поможет.

Правильный ответ о том, как получить расширение, доступное для имени файла в linux:

Пример печати всех расширений файлов в каталоге

Я думаю, что '$PATH_TO_SOMEWHERE' это что-то вроде '<directory>/*' .

В этом случае я бы изменил код на:

Если вы хотите сделать что-то более сложное с именами каталогов и текстовых файлов, вы можете:

Если в именах файлов есть пробелы, вы можете:

Я возьму его с вырезом

Мой захват с помощью awk будет примерно следующим.

Посмотрите другие вопросы по меткам scripting file bash или Задайте вопрос

Если четвёртый символ это - то файл не является исполняемым.

Сделать его исполняемым можно командой

chmod u+x script_1

-rwxrw-r--. 1 andrei andrei 5252 Nov 26 12:29 script_1

Обратите внимание на -rwx теперь четвёртый символ это x

В моей CentOS настроена подсветка исполняемых файлов, поэтому он теперь зелёный

Теперь выполнить скрипт можно командой

Конкретно этот скрипт должен принимать аргументы из командной строки , поэтому мы выполним

word1 добавится в log.txt а word2 нет, потому что word1 это первый аргумент а word2 второй.

Чтобы записывать вообще все аргументы заменим $1 на $*

Добавим в лог время выполнения команд (подробности здесь)

2020-09-20 17:48:27,404 one two three

Как вызвать скрипт из другого скрипта

Допустим из скрипта parent.sh вам нужно вызвать скрипт child.sh

Это если они в одной директории, если в разных - пишите путь до скрипта

Как назвать скрипт

Проверить не занято ли имя системой можно командой type.

Например, вы решили назвать свой скрипт test

test is a shell builtin

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

Вывод команды в переменную

Часто бывает нужно выполнить из скрипта команду и присвоить результат переменной.

Чтобы сделать это воспользуйтесь синтаксисом

Например, вам нужно проанализировать лог на количество ошибок и предупреждений

wc это команда, которая подсчитывает число слов

Аргументы из командной строки

Скрипт может принимать аргументы из командной строки

Первый аргумент обозначается как $1 второй как $2 и так далее

Рассмотрим пример ar.sh

Этот скрипт ждёт один внешний аргумент и присваивает его значение переменной AR

Затем это же значение выводится три раза

В C аналогичную функцию выполняет int argc, char* argv[]

Цикл for

В самом привычном виде цикл for можно записать так

Объединить строки

Конкатенация строк может быть сделана следующим образом

Функции

Чтобы не писать длинные команды вручную можно объединить их в функции.

Например, нужно менять местами экраны с помощью xrandr это довольно длинная команда и чтобы не выполнять эту команду каждый раз после перезагрузки можно написать функцию в .bashrc

Перезайдите в терминал.

Теперь, чтобы поменять экраны местами достаточно выполнить

Ещё один пример - функция внутри обычного скрипта, она может принимать аргументы, но пока что просто возвращает hi

Я хочу, чтобы получить имя файла (без расширения) и расширение отдельно.

лучшее решение я нашел до сих пор:

это неправильно, потому что он не работает, если имя файла содержит несколько . символы. Если, скажем, у меня есть a.b.js , он будет рассматривать a и b.js , вместо a.b и js .

это можно легко сделать в Python с

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

во-первых, получить имя файла без пути:

кроме того, вы можете сосредоточиться на последнем " / "пути вместо". который должен работать даже если у вас есть непредсказуемо расширениями:

дополнительные сведения см. В разделе расширение параметров оболочки в руководстве Bash.

обычно вы уже знаете расширение, поэтому вы можете использовать:

вы можете использовать магию переменных POSIX:

в этом есть оговорка, если ваше имя файла было в форме ./somefile.tar.gz затем echo $ жадно удалил бы самую длинную спичку в . и у вас будет пустая строка.

(вы можете обойти это с помощью временной переменной:

этой сайт больше объясняет.

это не работает, если файл не имеет расширения или имени файла. Вот что я использую; он использует только встроенные имена и обрабатывает больше (но не все) патологические имена файлов.

и вот некоторые тестовые примеры:

вам нужно предоставить basename с расширением, которое должно быть удалено, однако, если вы всегда выполняете tar С -z тогда вы знаете, что расширение будет .tar.gz .

это должно делать то, что вы хотите:

отлично работает, поэтому вы можете просто использовать:

команды, кстати, работают следующим образом.

команда NAME заменяет a "." символ, за которым следует любое число "." символы до конца строки, без ничего (т. е. он удаляет все из final "." до конца строки включительно). Это в основном не жадная подстановка с использованием обмана regex.

команда EXTENSION заменители a любое количество символов, за которыми следует "." символ в начале строки, без ничего (т. е. он удаляет все от начала строки до конечной точки, включительно). Это жадная подстановка, которая является действием по умолчанию.

используя Bash, есть также $ получить имя файла без расширения и $ чтобы получить расширение в одиночку. То есть,

можно использовать cut команда для удаления последних двух расширений ( ".tar.gz" часть):

как отметил Клейтон Хьюз в комментарии, это не будет работать на конкретном примере в вопросе. Поэтому в качестве альтернативы я предлагаю использовать sed с расширенными регулярными выражениями, например:

он работает, удаляя последние два (альфа-числовые) расширения безоговорочно.

[Обновлено снова после комментария от Андерса Линдаля]

нет необходимости беспокоиться с awk или sed или даже perl для этой простой задачи. Есть чистый-Баш, os.path.splitext() -совместимое решение, которое использует только разложений параметра.

разделить путь пути на пару (root, ext) такое, что root + ext == path и ext пусто или начинается с точки и содержит не более одного периода. Ведущие периоды базовое имя игнорируется; splitext('.cshrc') возвращает ('.cshrc', '') .

почитание ведущих периодов

игнорирование ведущих периодов

вот тестовые примеры для игнорирование ведущих периодов реализация, которая должна соответствовать ссылочной реализации Python на каждом входе.

вот некоторые альтернативные предложения (в основном в awk ), включая некоторые расширенные варианты использования, такие как извлечение номеров версий для пакетов программного обеспечения.

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

[Пересмотрено с однострочного до общего bash функции поведение сейчас соответствует dirname и basename служебные программы; обоснование добавил.]

на принято отвечать работает в типичный делам, а не в edge делам, а именно: