224 votes

Comment supprimer l'extension d'un nom de fichier dans un shell script ?

Quel est le problème avec le code suivant ?

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

Tel quel, j'obtiens la chaîne littérale $filename | cut -f1 -d'.' mais si j'enlève les guillemets, je n'obtiens rien. Pendant ce temps, en tapant

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

dans un shell me donne la sortie que je veux, test . Je sais déjà $filename s'est vu attribuer la bonne valeur. Ce que je veux faire, c'est affecter à une variable le nom du fichier sans l'extension.

25voto

Léa Gris Points 303

En utilisant uniquement le système intégré de POSIX :

#!/usr/bin/env sh
path=this.path/with.dots/in.path.name/filename.tar.gz

# Get the basedir without external command
# by stripping out shortest trailing match of / followed by anything
dirname=${path%/*}

# Get the basename without external command
# by stripping out longest leading match of anything followed by /
basename=${path##*/}

# Strip uptmost trailing extension only
# by stripping out shortest trailing match of dot followed by anything
oneextless=${basename%.*}; echo "$oneextless" 

# Strip all extensions
# by stripping out longest trailing match of dot followed by anything
noext=${basename%%.*}; echo "$noext"

# Printout demo
printf %s\\n "$path" "$dirname" "$basename" "$oneextless" "$noext"

Démonstration d'impression :

this.path/with.dots/in.path.name/filename.tar.gz
this.path/with.dots/in.path.name
filename.tar.gz
filename.tar
filename

8voto

C. Paul Bond Points 129
#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}

sorties :

/tmp/foo.bar.gz /tmp/foo.bar

Notez que seule la dernière extension est supprimée.

3voto

Alexey K. Points 81

Je recommande d'utiliser basename .
Il est par défaut dans Ubuntu, le code est visuellement simple et traite la majorité des cas.

Voici quelques sous-cas pour traiter les espaces et les multi-points/sous-extensions :

pathfile="../space fld/space -file.tar.gz"
echo ${pathfile//+(*\/|.*)}

Il se débarrasse généralement de l'extension en premier . mais nous échouons dans notre .. chemin

echo **"$(basename "${pathfile%.*}")"**  
space -file.tar     # I believe we needed exatly that

Voici une note importante :

J'ai utilisé des guillemets doubles à l'intérieur de guillemets doubles pour gérer les espaces. Les guillemets simples ne passeront pas à cause de l'écriture du $. Bash est inhabituel et lit "second "premier" guillemet" en raison de l'expansion.

Cependant, vous devez toujours penser à .hidden_files

hidden="~/.bashrc"
echo "$(basename "${hidden%.*}")"  # will produce "~" !!!  

pas le résultat attendu. Pour que cela se produise, utilisez $HOME ou /home/user_path/
parce qu'une fois encore, bash est "inhabituel" et ne développe pas "~" (recherchez bash BashPitfalls).

hidden2="$HOME/.bashrc" ;  echo '$(basename "${pathfile%.*}")'

2voto

FedonKadifeli Points 121

Les réponses fournies précédemment ont des problèmes avec les chemins contenant des points. Quelques exemples :

/xyz.dir/file.ext
./file.ext
/a.b.c/x.ddd.txt

Je préfère utiliser |sed -e 's/\.[^./]*$//' . Par exemple :

$ echo "/xyz.dir/file.ext" | sed -e 's/\.[^./]*$//'
/xyz.dir/file
$ echo "./file.ext" | sed -e 's/\.[^./]*$//'
./file
$ echo "/a.b.c/x.ddd.txt" | sed -e 's/\.[^./]*$//'
/a.b.c/x.ddd

Remarque : si vous souhaitez supprimer plusieurs extensions (comme dans le dernier exemple), utilisez la commande |sed -e 's/\.[^/]*$//' :

$ echo "/a.b.c/x.ddd.txt" | sed -e 's/\.[^/]*$//'
/a.b.c/x

Cependant, cette méthode échouera dans les "dot-files" sans extension :

$ echo "/a.b.c/.profile" | sed -e 's/\.[^./]*$//'
/a.b.c/

Pour couvrir également de tels cas, vous pouvez utiliser :

$ echo "/a.b.c/.profile" | sed -re 's/(^.*[^/])\.[^./]*$/\1/'
/a.b.c/.profile

1voto

booboo Points 90
#!/bin/bash
filename=program.c
name=$(basename "$filename" .c)
echo "$name"

sorties :

program

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X