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?
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
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"
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.
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//+(*\/|.*)}
:
-
${s
-- commencez par $s . -
//
remplacer chaque instance du modèle. -
+(
match un ou plusieurs de la liste dans la parenthèse. -
*\/
correspond à n'importe quoi avant/
. (1er modèle) -
|
Or. (modèle de séparateur.) -
.*
correspond à n'importe quoi après.
. (2ème modèle) -
)
fin liste . -
}
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:
- 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.
- 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
Voici oneliners:
-
$(basename ${s%.*})
-
$(basename ${s} .${s##*.})
j'en avais besoin, comme l'ont demandé bongbang et w4etwetwtwet.
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`
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.
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).
utilisez la commande basename. Sa page de manuel est ici: http://unixhelp.ed.ac.uk/CGI/man-cgi?basename