Extraire le fichier basename sans chemin et extension dans bash [dupliquer]

cette question a déjà une réponse ici:

  • Extrait de nom de fichier et extension en Bash 35 réponses

prénoms de fichier comme ceux-ci:

/the/path/foo.txt
bar.txt

j'espère avoir:

foo
bar

pourquoi ça ne marche pas?

#!/bin/bash

fullfile=
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname

Quelle est la bonne façon de le faire?

243
demandé sur alex 2010-04-19 05:25:28

9 réponses

vous n'avez pas à appeler la commande externe basename . À la place, vous pouvez utiliser les commandes suivantes:

$ s=/the/path/foo.txt
$ echo ${s##*/}
foo.txt
$ s=${s##*/}
$ echo ${s%.txt}
foo
$ echo ${s%.*}
foo

noter que cette solution devrait fonctionner dans tous les réservoirs récents ( post 2004 ) POSIX , (par ex. bash , dash , ksh , etc.).

Source: Commande Shell Langue 2.6.2 Paramètre D'Extension

Pour en savoir plus sur les Manipulations de Bash String: http://tldp.org/LDP/LG/issue18/bash.html

497
répondu ghostdog74 2017-04-04 11:12:26

la commande basename a deux invocations différentes; dans l'une, vous spécifiez juste le chemin, auquel cas il vous donne le dernier composant, tandis que dans l'autre vous donnez aussi un suffixe qu'il supprimera. Ainsi, vous pouvez simplifier votre code d'exemple en utilisant la deuxième invocation de basename. Aussi, faites attention à citer correctement les choses:

fbname=$(basename "" .txt)
echo "$fbname"
231
répondu Michael Aaron Safyan 2014-03-27 07:08:42

une combinaison de basename et des travaux de coupe fine, même en cas de double fin comme .tar.gz :

fbname=$(basename "$fullfile" | cut -d. -f1)

serait intéressant si cette solution nécessite moins de puissance arithmétique que L'Expansion du paramètre de Bash.

46
répondu kom lim 2015-12-21 22:22:38

Pure bash , no basename , pas de jonglage variable. Définir une chaîne et echo :

s=/the/path/foo.txt
echo ${s//+(*\/|.*)}

sortie:

foo

Remarque: le bash extglob doit être sur "on", ("la 1519290920" Ubuntu il est "sur" par défaut), si ce n'est pas, n':

shopt -s extglob

Marche à travers la ${s//+(*\/|.*)} :

  1. ${s -- commencez par $s .
  2. // remplacer chaque instance du modèle.
  3. +( match un ou plusieurs de la liste dans la parenthèse.
  4. *\/ correspond à n'importe quoi avant / . (1er modèle)
  5. | Or. (modèle de séparateur.)
  6. .* correspond à n'importe quoi après . . (2ème modèle)
  7. ) fin liste .
  8. } fin de l'extension du paramètre -- puisqu'il n'y a pas de / (qui précéderait un substitut de chaîne), les motifs appariés sont supprimés.

pertinent man bash background:

  1. modèle de substitution :
  ${parameter/pattern/string}
          Pattern substitution.  The pattern is expanded to produce a pat‐
          tern just as in pathname expansion.  Parameter is  expanded  and
          the  longest match of pattern against its value is replaced with
          string.  If pattern begins with /, all matches  of  pattern  are
          replaced   with  string.   Normally  only  the  first  match  is
          replaced.  If pattern begins with #, it must match at the begin‐
          ning of the expanded value of parameter.  If pattern begins with
          %, it must match at the end of the expanded value of  parameter.
          If string is null, matches of pattern are deleted and the / fol‐
          lowing pattern may be omitted.  If parameter is @ or *, the sub‐
          stitution  operation  is applied to each positional parameter in
          turn, and the expansion is the resultant list.  If parameter  is
          an  array  variable  subscripted  with  @ or *, the substitution
          operation is applied to each member of the array  in  turn,  and
          the expansion is the resultant list.
  1. correspondance étendue des motifs :
  If the extglob shell option is enabled using the shopt builtin, several
   extended  pattern  matching operators are recognized.  In the following
   description, a pattern-list is a list of one or more patterns separated
   by a |.  Composite patterns may be formed using one or more of the fol‐
   lowing sub-patterns:

          ?(pattern-list)
                 Matches zero or one occurrence of the given patterns
          *(pattern-list)
                 Matches zero or more occurrences of the given patterns
          +(pattern-list)
                 Matches one or more occurrences of the given patterns
          @(pattern-list)
                 Matches one of the given patterns
          !(pattern-list)
                 Matches anything except one of the given patterns
12
répondu agc 2017-05-28 20:10:39

Voici oneliners:

  1. $(basename ${s%.*})
  2. $(basename ${s} .${s##*.})

j'en avais besoin, comme l'ont demandé bongbang et w4etwetwtwet.

11
répondu sancho.s 2016-03-31 18:52:36

Voici une autre façon (plus complexe) d'obtenir soit le nom du fichier soit l'extension, utilisez d'abord la commande rev pour inverser le chemin du fichier, couper à partir de la première . et puis inverser le chemin du fichier à nouveau, comme ceci:

filename=`rev <<< "" | cut -d"." -f2- | rev`
fileext=`rev <<< "" | cut -d"." -f1 | rev`
8
répondu higuaro 2013-06-19 23:46:38

si vous voulez jouer gentiment avec Windows file paths (sous Cygwin), vous pouvez également essayer cela:

fname=${fullfile##*[/|\]}

cela va tenir compte des séparateurs antislash lors de L'utilisation de BaSH sur Windows.

2
répondu Apelsin 2013-08-05 07:48:23

juste une alternative que je suis venu avec pour extraire une extension, en utilisant les poteaux dans ce fil avec ma propre petite base de connaissances qui était plus familière pour moi.

ext="$(rev <<< "$(cut -f "1" -d "." <<< "$(rev <<< "file.docx")")")"

Note: s'il vous plaît, conseillez-moi sur l'utilisation des guillemets; cela a fonctionné pour moi, mais il se peut que je manque quelque chose sur leur utilisation correcte (j'en utilise probablement trop).

0
répondu Diomoid 2015-03-02 18:16:13

utilisez la commande basename. Sa page de manuel est ici: http://unixhelp.ed.ac.uk/CGI/man-cgi?basename

-10
répondu Bandicoot 2012-07-01 18:19:08