web-dev-qa-db-fra.com

Comment puis-je supprimer l'extension d'un nom de fichier dans un script Shell?

Quel est le problème avec le code suivant?

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

Telle quelle, j'obtiens la chaîne littérale $filename | cut -f1 -d'.', mais si je supprime les guillemets, je ne reçois 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à que $filename a reçu la bonne valeur. Ce que je veux faire, c'est assigner à une variable le nom de fichier sans l'extension.

97
mimicocotopus

Vous devriez utiliser la substitution commande syntax $(command) lorsque vous souhaitez exécuter une commande dans script/command.

Donc, votre ligne serait 

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

Explication du code:

  1. echo récupère la valeur de la variable $filename et l'envoie à la sortie standard
  2. Nous saisissons ensuite la sortie et la transmettons à la commande cut
  3. La cut utilisera le. comme séparateur (également appelé séparateur) pour couper la chaîne en segments et par -f nous sélectionnons le segment que nous voulons avoir en sortie
  4. Ensuite, la substitution de commande $() obtiendra la sortie et renverra sa valeur
  5. La valeur renvoyée sera assignée à la variable nommée name

Notez que cela donne la partie de la variable jusqu'à la première période .:

$ 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
72
Rohan

Vous pouvez également utiliser l'expansion des paramètres:

$ filename=foo.txt
$ echo "${filename%.*}"
foo
170
chepner

Si vous connaissez l'extension, vous pouvez utiliser basename

$ basename /home/jsmith/base.wiki .wiki
base
86
Steven Penny

Si votre nom de fichier contient un point (autre que celui de l'extension), utilisez ceci:

echo $filename | rev | cut -f 2- -d '.' | rev
15
manish_s
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

utilisez ce que vous voulez. Ici, je suppose que le dernier . (point) suivi du texte est une extension.

13
Raghwendra

Comme l'a souligné Hawker65 dans le commentaire de chepner answer, la solution la plus votée ne prend en charge ni les extensions multiples (telles que filename.tar.gz), ni les points dans le reste du chemin (tel que this.path/with .dots/in.path.name) . Une solution possible est:

a=this.path/with.dots/in.path.name/filename.tar.gz
echo $(dirname $a)/$(basename $a | cut -d. -f1)
1
MadMage
#!/bin/bash
filename=program.c
name=$(basename "$filename" .c)
echo "$name"

les sorties:

program
0
booboo

Deux problèmes avec votre code:

  1. Vous avez utilisé un '(coche) au lieu d'un `(coche arrière) pour entourer les commandes qui génèrent la chaîne que vous voulez stocker dans la variable.
  2. Vous n'avez pas "renvoyé" la variable "$ filename" au tube dans la commande "couper".

Je changerais votre code en "nom =` echo $ nom_fichier | cut -f 1 -d '.' `", comme indiqué ci-dessous (à nouveau, notez les graduations arrière entourant la définition de variable de nom):

$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$> 
0
FanDeLaU
#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}

les sorties:

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

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

0
C. Paul Bond

Ma recommandation est d'utiliser le nom de base.
C’est par défaut dans Ubuntu, un code visuellement simple et une majorité de cas. Voici quelques sous-cas pour gérer les espaces et les sous-extensions/sous-extensions:

pathfile = "../ space fld/space -file.tar.gz"

echo $ {pathfile // + (/|. )}
En général, il se débarrasse de l’extension. mais a échoué dans notre .. chemin

echo "$ (nom de base" $ {pathfile%. *} ")"
space -file.tar # Je crois que nous avions exactement besoin de cela

Voici une remarque importante: j'ai utilisé des guillemets entre guillemets pour traiter les espaces. La citation simple ne sera pas transmise en raison de l'envoi d'un SMS au $. Bash est inhabituel et se lit "deuxième", "premier" guillemets "en raison de l'expansion.

Cependant, vous devez toujours penser à .hidden_files

hidden = "~/.bashrc" echo "$ (nom_base" $ {hidden%.} ")" # produira "~" !!!
pas le "" résultat attendu. Pour ce faire, utilisez $ HOME ou/home/chemin_utilisateur /
Parce que bash est encore "inhabituel" et ne développe pas "~" (recherche de bash BashPitfalls)
hidden2 = "$ HOME/.bashrc"; echo '$ (nom_base "$ {pathfile%.
}")'

0
Alexey K.