Отримати останнє ім’я / ім'я файлу в аргументі шляху файлу в Bash


228

Я намагаюся написати гачок після завершення роботи для SVN, який розміщений на нашому сервері розробки. Моя мета - спробувати автоматично оформити копію здійсненого проекту в каталог, де він розміщений на сервері. Однак мені потрібно вміти читати лише останню директорію в рядку каталогів, передану скрипту, щоб перейти в той самий підкаталог, де розміщуються наші проекти.

Наприклад, якщо я приймаю SVN на проект "приклад", мій скрипт отримує "/ usr / local / svn / repos / example" в якості першого аргументу. Мені потрібно дістати лише "приклад" з кінця рядка, а потім закріпити його іншою рядком, щоб я міг перевірити "/ server / root / example" і побачити зміни в прямому ефірі.

Відповіді:


344

basename видаляє префікс каталогу шляху:

$ basename /usr/local/svn/repos/example
example
$ echo "/server/root/$(basename /usr/local/svn/repos/example)"
/server/root/example

2
базове ім’я, безумовно, те, що я шукаю. Як можна отримати базове ім'я аргументу, збереженого у змінній? Напр.SUBDIR="/path/to/whatever/$(basename $1)"
TJ L

5
@ tj111: звучить як ні $1, або $1порожнє
sth

на жаль, якщо ви загортаєте команди, ім'я бази не є гарною ідеєю. просто щось пам’ятати
dtc

98

Наступний підхід може бути використаний для отримання будь-якого шляху імені шляху:

some_path=a/b/c
echo $(basename $some_path)
echo $(basename $(dirname $some_path))
echo $(basename $(dirname $(dirname $some_path)))

Вихід:

c
b
a

1
не працює з доріжками, у яких є пробіли ... ви можете подолати це цитатами ... що так чи інакше працюєecho "$(basename "$(dirname "$pathname")")"
Рей Фосс

75

Bash може отримати останню частину шляху без виклику зовнішньої basename:

subdir="/path/to/whatever/${1##*/}"

2
На моєму Mac використання позначень підрядків більше, ніж на порядок швидше, ніж dirname / basename для випадку, коли ви робите щось тривіальне для кожного з кількох тисяч файлів.
Джордж

1
d=/home/me/somefolder;subdir="/$d/${1##*/}"У мене вийшло щось на кшталт //home/me/somefolder//$ d насправді виходить із циклу. for d in $(find $SOMEFOLDER -maxdepth 1 -type d);Використовуючи subdir=$(basename $d)роботи, як очікувалося.
Buttle Butkus

1
@ButtleButkus: Вам слід використовувати whileзамість того, forщоб перебирати результат find( find -print0 | xargs -0краще) або використовувати глобулінг: for d in $SOMEFOLDER/*/(фінальний косий ривок працює на зразок -type d- ви можете використовувати **Bash 4 для рекурсії, якщо у вас є shopt -s globstar, але повідомлення "Аргумент занадто довгий" повідомлення є можливо). Зауважте, що ${1}частина команди являє собою перший аргумент сценарію або функції. Можливо, вам доведеться скористатися ${d##*/}якоюсь іншою специфікацією змінної чи аргументу або переконатися, що аргумент передається$1
Призупинено до подальшого повідомлення.

2
@DennisWilliamson Дякую за те, що поділилися . Для будь-яких майбутніх читачів, які починають цікавитись, чому це не працює, або я єдиний дурень тут out. Вище відповідь передбачає, що $1містить the path from which last component is to be taken out. Я пропустив цю частину. Мій випадок використання: target_path='/home/user/dir1/dir2/dir3/'; target_path="${target_path%/}"; last_component=${target_path##*/}; echo $last_component- Твори 😉
Винай Віш

2
Дивіться тут, щоб пояснити, як і чому ${1##*/} працює: unix.stackexchange.com/a/171786/15070
Матвій
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.