Как я могу удалить расширение имени файла в сценарии оболочки?
Что не так со следующим кодом?
name='$filename | cut -f1 -d'.''
Как есть, я получаю буквальную строку $filename | cut -f1 -d'.'
$filename | cut -f1 -d'.'
, но если я уберу цитаты, я ничего не получу. Тем временем печатать
"test.exe" | cut -f1 -d'.'
в оболочке дает мне вывод, который я хочу, test
. Я уже знаю, что $filename
было присвоено правильное значение. Я хочу назначить переменной имя файла без расширения.
Ответы
Ответ 1
Вы должны использовать синтаксис подстановки команд $(command)
когда вы хотите выполнить команду в сценарии/команде.
Так что ваша линия будет
name=$(echo "$filename" | cut -f 1 -d '.')
Объяснение кода:
-
echo
получить значение переменной $filename
и отправить его на стандартный вывод - Затем мы берем вывод и передаем его в команду
cut
-
cut
будет использовать. в качестве разделителя (также известного как разделитель) для разрезания строки на сегменты и с помощью -f
мы выбираем, какой сегмент мы хотим иметь в выводе - Тогда подстановка команды
$()
получит вывод и вернет его значение - Возвращенное значение будет присвоено переменной с именем
name
Обратите внимание, что это дает часть переменной до первого периода .
:
$ filename=hello.world
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello.hello.hello
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello
$ echo "$filename" | cut -f 1 -d '.'
hello
Ответ 2
Вы также можете использовать расширение параметра:
$ filename=foo.txt
$ echo "${filename%.*}"
foo
Ответ 3
Если вы знаете расширение, вы можете использовать basename
$ basename /home/jsmith/base.wiki .wiki
base
Ответ 4
Если ваше имя файла содержит точку (отличную от одной из расширений), используйте следующее:
echo $filename | rev | cut -f 2- -d '.' | rev
Ответ 5
file1=/tmp/main.one.two.sh
t=$(basename "$file1") # output is main.one.two.sh
name=$(echo "$file1" | sed -e 's/\.[^.]*$//') # output is /tmp/main.one.two
name=$(echo "$t" | sed -e 's/\.[^.]*$//') # output is main.one.two
используйте то, что вы хотите. Здесь я предполагаю, что в прошлом .
(точка), за которой следует текст, является расширением.
Ответ 6
Как указал Hawker65 в комментарии к ответу chepner, решение с наибольшим количеством голосов не заботится ни о нескольких расширениях (например, filename.tar.gz), ни о точках в остальной части пути (например, this.path/with)..dots/in.path.name). Возможное решение:
a=this.path/with.dots/in.path.name/filename.tar.gz
echo $(dirname $a)/$(basename $a | cut -d. -f1)
Ответ 7
Я рекомендую использовать basename
.
Это по умолчанию в Ubuntu, визуально простой код и имеет дело с большинством случаев.
Вот несколько подслучаев для работы с пробелами и многоточечным/под-расширением:
pathfile="../space fld/space -file.tar.gz"
echo ${pathfile//+(*\/|.*)}
Обычно он сначала избавляется от расширения .
, но терпит неудачу в нашем пути ..
echo **"$(basename "${pathfile%.*}")"**
space -file.tar # I believe we needed exatly that
Вот важное замечание:
Я использовал двойные кавычки внутри двойных кавычек, чтобы иметь дело с пробелами. Одиночная кавычка не пройдет из-за отправки $. Bash необычен и читает "вторые" первые "цитаты" из-за расширения.
Тем не менее, вам все еще нужно подумать о .hidden_files
hidden="~/.bashrc"
echo "$(basename "${hidden%.*}")" # will produce "~" !!!
не ожидаемый "" результат. Чтобы это произошло, используйте $HOME
или /home/user_path/
потому что опять bash "необычен" и не расширяет "~" (поиск bash BashPitfalls)
hidden2="$HOME/.bashrc" ; echo '$(basename "${pathfile%.*}")'
Ответ 8
Две проблемы с вашим кодом:
- Вы использовали '(tick) вместо `(back tick), чтобы окружать команды, которые генерируют строку, которую вы хотите сохранить в переменной.
- Вы не "эхом" указали переменную "$ filename" на трубку в команду "вырезать".
Я бы изменил ваш код на "name=` echo $filename | cut -f 1 -d '.' `", как показано ниже (опять же, обратите внимание на обратные тики, окружающие определение переменной имени):
$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$>
Ответ 9
#!/bin/bash
filename=program.c
name=$(basename "$filename" .c)
echo "$name"
выходы:
program
Ответ 10
#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}
выходы:
/tmp/foo.bar.gz /tmp/foo.bar
Обратите внимание, что удаляется только последнее расширение.
Ответ 11
Лучшее решение:
filename=myfile.txt
echo ${filename%txt}
Выход:
myfile.
Убрал расширение txt.
Ответ 12
Поправьте меня, если я ошибаюсь, пожалуйста.
Когда я пытаюсь сделать какие-либо обновления для файла из CLI (интерфейс командной строки). Я делаю, как показано ниже:
1- Например, у меня есть файл test.txt, который я сейчас хорошо создаю:
touch test.txt
2- Теперь я хорошо создаю резервную копию файла с помощью следующей команды:
cp test.txt{,.bak}
3- Чтобы не видеть каталог
ll
Теперь мы находим два файла test.txt и test.txt.bak
4- Теперь мы удаляем оригинальный файл test.txt, если допустили ошибки внутри
rm test.txt
5- Команда ниже хорошо восстанавливает исходный файл из резервной копии
cp test.txt.bak test.txt
6- Если мы сейчас перечислим файлы каталогов, мы найдем test.txt и
test.txt.bak:
ll
7- Теперь удалите файл test.txt.bak, который вам больше не нужен, как показано ниже
rm test.txt.bak
8- Вы сделали обновления, пока были в безопасности.