programacion - script linux bash
Obtenga solo el nombre de archivo de una ruta en un script Bash (6)
Esta pregunta ya tiene una respuesta aquí:
- Extraer nombre de archivo y extensión en Bash 35 respuestas
¿Cómo puedo obtener solo el nombre de archivo sin la extensión y sin ruta?
Lo siguiente no me da ninguna extensión, pero todavía tengo el camino adjunto:
source_file_filename_no_ext=${source_file%.*}
Algunas opciones alternativas más porque las expresiones regulares (regi?) Son impresionantes!
Aquí hay una expresión regular simple para hacer el trabajo:
regex="[^/]*$"
Ejemplo (grep):
FP="/hello/world/my/file/path/hello_my_filename.log"
echo $FP | grep -oP "$regex"
#Or using standard input
grep -oP "$regex" <<< $FP
Ejemplo (awk):
echo $FP | awk ''{match($1, "$regex",a)}END{print a[0]}
#Or using stardard input
awk ''{match($1, "$regex",a)}END{print a[0]} <<< $FP
Si necesita una expresión regular más complicada: por ejemplo, su ruta está envuelta en una cadena.
StrFP="my string is awesome file: /hello/world/my/file/path/hello_my_filename.log sweet path bro."
#this regex matches a string not containing / and ends with a period
#then at least one word character
#so its useful if you have an extension
regex="[^/]*/./w{1,}"
#usage
grep -oP "$regex" <<< $StrFP
#alternatively you can get a little more complicated and use lookarounds
#this regex matches a part of a string that starts with / that does not contain a /
##then uses the lazy operator ? to match any character at any amount (as little as possible hence the lazy)
##that is followed by a space
##this allows use to match just a file name in a string with a file path if it has an exntension or not
##also if the path doesnt have file it will match the last directory in the file path
##however this will break if the file path has a space in it.
regex="(?<=/)[^/]*?(?=/s)"
#to fix the above problem you can use sed to remove spaces from the file path only
## as a side note unfortunately sed has limited regex capibility and it must be written out in long hand.
NewStrFP=$(echo $StrFP | sed ''s:/(/[a-z]*/)/( /)/([a-z]*//):/1/3:g'')
grep -oP "$regex" <<< $NewStrFP
Solución total con Regexes:
Esta función puede proporcionarle el nombre de archivo con o sin extensión de una ruta de archivo de Linux, incluso si el nombre de archivo tiene varios "." S. También puede manejar espacios en la ruta de archivo y si la ruta del archivo está incrustada o envuelta en una cadena.
#you may notice that the sed replace has gotten really crazy looking
#I just added all of the allowed characters in a linux file path
function Get-FileName(){
local FileString="$1"
local NoExtension="$2"
local FileString=$(echo $FileString | sed ''s:/(/[a-zA-Z0-9/</>/|///:/)/(/&/;/,/?/*]*/)/( /)/([a-zA-Z0-9/</>/|///:/)/(/&/;/,/?/*]*//):/1/3:g'')
local regex="(?<=/)[^/]*?(?=/s)"
local FileName=$(echo $FileString | grep -oP "$regex")
if [[ "$NoExtension" != "" ]]; then
sed ''s:/.[^/.]*$::g'' <<< $FileName
else
echo "$FileName"
fi
}
## call the function with extension
Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro."
##call function without extension
Get-FileName "my string is awesome file: /hel lo/world/my/file test/path/hello_my_filename.log sweet path bro." "1"
Si tiene que meterse con una ruta de Windows, puede comenzar con esta:
[^//]*$
Aquí hay una manera fácil de obtener el nombre del archivo desde una ruta:
echo "$PATH" | rev | cut -d"/" -f1 | rev
Para eliminar la extensión que puede usar, asumiendo que el nombre del archivo tiene solo UN punto (el punto de extensión):
cut -d"." -f1
La mayoría de los sistemas operativos similares a UNIX tienen un ejecutable de basename
para un propósito muy similar (y dirname
para la ruta):
pax> a=/tmp/file.txt
pax> b=$(basename $a)
pax> echo $b
file.txt
Desafortunadamente, eso solo te da el nombre del archivo, incluida la extensión, por lo que también deberías encontrar una forma de eliminarlo.
Entonces, dado que tienes que hacer eso de todos modos, también puedes encontrar un método que pueda quitarte el camino y la extensión.
Una forma de hacerlo (y esta es una solución de bash
-only, que no necesita otros ejecutables):
pax> a=/tmp/xx/file.tar.gz
pax> xpath=${a%/*}
pax> xbase=${a##*/}
pax> xfext=${xbase##*.}
pax> xpref=${xbase%.*}
pax> echo;echo path=${xpath};echo pref=${xpref};echo ext=${xfext}
path=/tmp/xx
pref=file.tar
ext=gz
Ese pequeño fragmento establece xpath
(la ruta del archivo), xpref
(el prefijo del archivo, lo que estabas pidiendo específicamente) y xfext
(la extensión del archivo).
basename
soluciones basename
y dirname
son más convenientes. Esos son comandos alternativos:
FILE_PATH="/opt/datastores/sda2/test.old.img"
echo "$FILE_PATH" | sed "s/.*////"
Esto devuelve test.old.img
como basename
.
Este es el nombre de archivo salt sin extensión:
echo "$FILE_PATH" | sed -r "s/.+//(.+)/..+//1/"
Devuelve test.old
.
Y la siguiente declaración da la ruta completa como el comando dirname
.
echo "$FILE_PATH" | sed -r "s/(.+)//.+//1/"
Devuelve /opt/datastores/sda2
$ file=${$(basename $file_path)%.*}
$ source_file_filename_no_ext=${source_file%.*}
$ echo ${source_file_filename_no_ext##*/}