Réponses:
basename
de GNU coreutils peut vous aider à faire ce travail:
$ basename /root/video.mp4
video.mp4
Si vous connaissez déjà l'extension du fichier, vous pouvez invoquer en basename
utilisant la syntaxe basename NAME [SUFFIX]
pour la supprimer:
$ basename /root/video.mp4 .mp4
video
Ou une autre option serait de tout couper après le dernier point en utilisant sed
:
$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old
La solution la plus simple est de tout supprimer jusqu'à la dernière apparition de /
:
echo /root/video.mp4 | sed 's/.*\///'
Utilisez l'une des méthodes suivantes:
out_file="${in_file##*/}"
out_file="$(basename $in_file)"
out_file="$(echo $in_file | sed 's=.*/==')"
out_file="$(echo $in_file | awk -F"/" '{ print $NF }')"
ps. Vous obtenez la même chaîne, car dans votre instruction \(.*\.\)
correspond à la chaîne depuis le début jusqu'à dot ( /root/video.
), puis vous ajoutez manuellement.mp4
ce qui est le même que dans votre chaîne d'origine. Vous devriez utiliser à la s=.*\([^/]*\)=\1=
place.
Mise à jour: (la première est corrigée maintenant)
Pour obtenir le seul nom de fichier sans extension, vous pouvez:
out_file="$(echo $in_file | sed 's=.*/==;s/\.[^.]*$/.new_ext/')"
out_file="$(echo $in_file | sed 's=\([^/]*\)\.[^./]*$=\1.new_ext=')"
out_file="$(echo $in_file | awk -F"/" '{ gsub (/\.[^/.]*$/,".new_ext",$NF);print $NF }'
my.file.tar.gz
.
sed
et awk
. Fixé. Je vous remercie.
L'un des principes fondamentaux de l'utilisation de l'expression régulière est que les modèles sont gourmands par nature lors de la spécification du caractère générique. Bien que la réponse proposée par @uloBasEI soit certainement une réponse fonctionnelle, elle nécessite également l'utilisation de la commande basename. La question d'origine de @Shixons demande une solution utilisant uniquement sed.
Avant de continuer, il est toujours utile de savoir quelle version de sed est la cible. Je suppose BSD (tel que livré avec OSX).
Tout d'abord, le modèle proposé dans la question d'origine ne fonctionne pas car il capture tout depuis le début de la chaîne d'entrée jusqu'au dernier point inclus. Sans ancres, cette recherche engloutira tout de gauche à droite. Le motif apparié "/ 1", par conséquent, est tout jusqu'au dernier point inclus. Même un nom de fichier avec plusieurs points sera englouti en entier. Pas du tout le résultat souhaité.
La première étape consiste à établir une stratégie d'identification des modèles. Ici, vous souhaitez vous débarrasser de tout à gauche du nom de fichier (nous traiterons de l'extension plus tard):
out_file="$(echo $in_file | sed 's/^\(\/.*\/\)*.*/\1/')"
La recherche correspond au début de la chaîne. Il correspond à un modèle de "/.*" zéro ou plusieurs fois et supprime tout par la suite. Nous imprimons les motifs assortis avec "\ 1". Nous ne cherchons pas globalement; nous recherchons depuis le début de la chaîne en spécifiant l'ancre ^.
Nous obtenons une meilleure clarté en activant l'option "-E" afin que nous n'ayons pas à échapper les parenthèses:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*.*/\1/')"
Nous avons donc maintenant la partie à gauche. Ajoutons la partie à droite. Notez que nous devons conserver la partie gauche en tant que motif, car c'est ainsi que nous pouvons spécifier qu'elle apparaît zéro ou plusieurs fois. Tout ce que nous faisons maintenant est d'ajouter un motif pour la pièce de droite:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)/\2/')"
Nous imprimons uniquement la deuxième correspondance, éliminant ainsi tout sauf le nom de fichier. Mais nous devons toujours supprimer l'extension du nom de fichier.
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2/')"
Le "$" à la fin est facultatif.
Enfin, pour ajouter la nouvelle extension que vous venez de réviser comme suit:
out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2.mp4/')"
Une optimisation supplémentaire consiste à rendre la première barre oblique facultative pour gérer les chemins relatifs:
out_file="$(echo $in_file | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2.mp4/')"
Je suis tombé sur cette question en étant paresseux en cherchant un motif sed pour remplacer le nom de base . Je travaille sur un système dépouillé sur lequel cette commande n'est pas installée.
sed 's/\.[^.]*$//'
comme vous l'avez fait, échouera pour (caché).filename
et.
et les..
répertoires