Подтвердить что ты не робот

Как я могу удалить расширение имени файла в сценарии оболочки?

Что не так со следующим кодом?

name='$filename | cut -f1 -d'.''

Как есть, я получаю буквальную строку $filename | cut -f1 -d'.' $filename | cut -f1 -d'.' , но если я уберу цитаты, я ничего не получу. Тем временем печатать

"test.exe" | cut -f1 -d'.'

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

4b9b3361

Ответ 1

Вы должны использовать синтаксис подстановки команд $(command) когда вы хотите выполнить команду в сценарии/команде.

Так что ваша линия будет

name=$(echo "$filename" | cut -f 1 -d '.')

Объяснение кода:

  1. echo получить значение переменной $filename и отправить его на стандартный вывод
  2. Затем мы берем вывод и передаем его в команду cut
  3. cut будет использовать. в качестве разделителя (также известного как разделитель) для разрезания строки на сегменты и с помощью -f мы выбираем, какой сегмент мы хотим иметь в выводе
  4. Тогда подстановка команды $() получит вывод и вернет его значение
  5. Возвращенное значение будет присвоено переменной с именем 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- Вы сделали обновления, пока были в безопасности.