Wyodrębnij nazwę pliku i rozszerzenie w Bash
Chcę pobrać nazwę pliku (bez rozszerzenia) i rozszerzenie osobno.
Najlepsze rozwiązanie jakie dotychczas znalazłem to:
NAME=`echo "$FILE" | cut -d'.' -f1`
EXTENSION=`echo "$FILE" | cut -d'.' -f2`
Jest to złe, ponieważ nie działa, jeśli nazwa pliku zawiera wiele znaków {[2] }. Jeśli, powiedzmy, mam a.b.js
, rozważy a
i b.js
, zamiast a.b
i js
.
Można to łatwo zrobić w Pythonie za pomocą
file, ext = os.path.splitext(path)
Ale wolałbym nie uruchamiać interpretera Pythona tylko w tym celu, jeśli to możliwe.
Any lepsze pomysły?
30 answers
Najpierw pobierz nazwę pliku bez ścieżki:
filename=$(basename -- "$fullfile")
extension="${filename##*.}"
filename="${filename%.*}"
Alternatywnie, możesz skupić się na ostatnim '/' ścieżki zamiast na '.'które powinno działać nawet jeśli masz nieprzewidywalne rozszerzenia plików:
filename="${fullfile##*/}"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-30 13:58:25
~% FILE="example.tar.gz"
~% echo "${FILE%%.*}"
example
~% echo "${FILE%.*}"
example.tar
~% echo "${FILE#*.}"
tar.gz
~% echo "${FILE##*.}"
gz
Aby uzyskać więcej szczegółów, zobacz rozszerzenie parametrów powłoki w podręczniku Bash.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 16:58:03
Zazwyczaj znasz już rozszerzenie, więc możesz chcieć użyć:
basename filename .extension
Na przykład:
basename /path/to/dir/filename.txt .txt
I otrzymujemy
filename
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-19 10:56:09
Możesz użyć magii zmiennych POSIX:
bash-3.2$ FILENAME=somefile.tar.gz
bash-3.2$ echo ${FILENAME%%.*}
somefile
bash-3.2$ echo ${FILENAME%.*}
somefile.tar
Jest zastrzeżenie, że jeśli Twoja nazwa pliku ma postać ./somefile.tar.gz
, to echo ${FILENAME%%.*}
chciwie usunie najdłuższy pasujący do .
i będziesz miał pusty łańcuch.
(możesz obejść to za pomocą zmiennej tymczasowej:
FULL_FILENAME=$FILENAME
FILENAME=${FULL_FILENAME##*/}
echo ${FILENAME%%.*}
)
${variable%pattern}
Trim the shortest match from the end
${variable##pattern}
Trim the longest match from the beginning
${variable%%pattern}
Trim the longest match from the end
${variable#pattern}
Trim the shortest match from the beginning
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-05 15:40:05
To nie działa, jeśli plik nie ma rozszerzenia lub nazwy pliku. Oto, czego używam; używa tylko wbudowanych i obsługuje więcej (ale nie wszystkie) patologicznych nazw plików.
#!/bin/bash
for fullpath in "$@"
do
filename="${fullpath##*/}" # Strip longest match of */ from start
dir="${fullpath:0:${#fullpath} - ${#filename}}" # Substring from 0 thru pos of filename
base="${filename%.[^.]*}" # Strip shortest match of . plus at least one non-dot char from end
ext="${filename:${#base} + 1}" # Substring from len of base thru end
if [[ -z "$base" && -n "$ext" ]]; then # If we have an extension and no base, it's really the base
base=".$ext"
ext=""
fi
echo -e "$fullpath:\n\tdir = \"$dir\"\n\tbase = \"$base\"\n\text = \"$ext\""
done
A oto kilka testów:
$ basename-and-extension.sh / /home/me/ /home/me/file /home/me/file.tar /home/me/file.tar.gz /home/me/.hidden /home/me/.hidden.tar /home/me/.. . /: dir = "/" base = "" ext = "" /home/me/: dir = "/home/me/" base = "" ext = "" /home/me/file: dir = "/home/me/" base = "file" ext = "" /home/me/file.tar: dir = "/home/me/" base = "file" ext = "tar" /home/me/file.tar.gz: dir = "/home/me/" base = "file.tar" ext = "gz" /home/me/.hidden: dir = "/home/me/" base = ".hidden" ext = "" /home/me/.hidden.tar: dir = "/home/me/" base = ".hidden" ext = "tar" /home/me/..: dir = "/home/me/" base = ".." ext = "" .: dir = "" base = "." ext = ""
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-10 06:13:08
Możesz użyć basename
.
Przykład:
$ basename foo-bar.tar.gz .tar.gz
foo-bar
Musisz podać basename z rozszerzeniem, które zostanie usunięte, jednak jeśli zawsze wykonujesz tar
z -z
, to wiesz, że rozszerzenie będzie .tar.gz
.
To powinno robić to, co chcesz:
tar -zxvf $1
cd $(basename $1 .tar.gz)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-05 08:56:05
pax> echo a.b.js | sed 's/\.[^.]*$//'
a.b
pax> echo a.b.js | sed 's/^.*\.//'
js
Działa dobrze, więc możesz po prostu użyć:
pax> FILE=a.b.js
pax> NAME=$(echo "$FILE" | sed 's/\.[^.]*$//')
pax> EXTENSION=$(echo "$FILE" | sed 's/^.*\.//')
pax> echo $NAME
a.b
pax> echo $EXTENSION
js
Przy okazji komendy działają w następujący sposób.
Polecenie dla NAME
zastępuje znak "."
, po którym następuje dowolna liczba znaków nie-{[3] } aż do końca linii, z niczym(tzn. usuwa wszystko od ostatniego "."
do końca linii, włącznie). Jest to w zasadzie nie chciwe podstawienie za pomocą sztuczek regex.
Polecenie dla EXTENSION
zastępuje dowolną liczbę znaków, po której następuje "."
znak na początku linii, z niczym (tzn. usuwa wszystko od początku linii do ostatniej kropki, włącznie). Jest to zachłanna substytucja, która jest domyślną akcją.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-05 01:07:22
Mellen pisze w komentarzu do wpisu na blogu:
Używając Bash, istnieje również ${file%.*}
, aby uzyskać nazwę pliku bez rozszerzenia i ${file##*.}
, aby uzyskać samo rozszerzenie. Czyli
file="thisfile.txt"
echo "filename: ${file%.*}"
echo "extension: ${file##*.}"
Wyjścia:
filename: thisfile
extension: txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 16:58:54
Możesz użyć cut
polecenie usunięcia dwóch ostatnich rozszerzeń (część ".tar.gz"
):
$ echo "foo.tar.gz" | cut -d'.' --complement -f2-
foo
Jak zauważył Clayton Hughes w komentarzu, nie będzie to działać dla rzeczywistego przykładu w pytaniu. Więc jako alternatywę proponuję użycie sed
z rozszerzonymi wyrażeniami regularnymi, takimi jak:
$ echo "mpc-1.0.1.tar.gz" | sed -r 's/\.[[:alnum:]]+\.[[:alnum:]]+$//'
mpc-1.0.1
Działa poprzez bezwarunkowe usunięcie dwóch ostatnich (alfanumerycznych) rozszerzeń.
[Zaktualizowano ponownie po komentarzu od Andersa Lindahla]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 08:08:34
Nie trzeba przejmować się awk
lub sed
lub nawet perl
dla tego prostego zadania. Istnieje rozwiązanie pure-Bash, kompatybilne z os.path.splitext()
, które używa tylko rozszerzeń parametrów.
Implementacja Odniesienia
Dokumentacja os.path.splitext(path)
:
Podziel ścieżkę na parę
(root, ext)
taką, żeroot + ext == path
, a ext jest pusty lub zaczyna się kropką i zawiera co najwyżej jeden kropkę. Pierwsze okresy w nazwie bazowej są ignorowane;splitext('.cshrc')
zwraca('.cshrc', '')
.
Kod Pythona:
root, ext = os.path.splitext(path)
Implementacja Bash
Honorowanie okresów wiodących
root="${path%.*}"
ext="${path#"$root"}"
Ignorowanie okresów czołowych
root="${path#.}";root="${path%"$root"}${root%.*}"
ext="${path#"$root"}"
Testy
Oto przypadki testowe dla implementacji ignorującej okresy wiodące , która powinna pasować do implementacji referencyjnej Pythona na każdym wejściu.
|---------------|-----------|-------|
|path |root |ext |
|---------------|-----------|-------|
|' .txt' |' ' |'.txt' |
|' .txt.txt' |' .txt' |'.txt' |
|' txt' |' txt' |'' |
|'*.txt.txt' |'*.txt' |'.txt' |
|'.cshrc' |'.cshrc' |'' |
|'.txt' |'.txt' |'' |
|'?.txt.txt' |'?.txt' |'.txt' |
|'\n.txt.txt' |'\n.txt' |'.txt' |
|'\t.txt.txt' |'\t.txt' |'.txt' |
|'a b.txt.txt' |'a b.txt' |'.txt' |
|'a*b.txt.txt' |'a*b.txt' |'.txt' |
|'a?b.txt.txt' |'a?b.txt' |'.txt' |
|'a\nb.txt.txt' |'a\nb.txt' |'.txt' |
|'a\tb.txt.txt' |'a\tb.txt' |'.txt' |
|'txt' |'txt' |'' |
|'txt.pdf' |'txt' |'.pdf' |
|'txt.tar.gz' |'txt.tar' |'.gz' |
|'txt.txt' |'txt' |'.txt' |
|---------------|-----------|-------|
Wyniki Badań
Wszystkie testy przeszły pomyślnie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-19 23:35:04
Oto kilka alternatywnych sugestii (głównie w awk
), w tym kilka zaawansowanych przypadków użycia, takich jak wyodrębnianie numerów wersji pakietów oprogramowania.
f='/path/to/complex/file.1.0.1.tar.gz'
# Filename : 'file.1.0.x.tar.gz'
echo "$f" | awk -F'/' '{print $NF}'
# Extension (last): 'gz'
echo "$f" | awk -F'[.]' '{print $NF}'
# Extension (all) : '1.0.1.tar.gz'
echo "$f" | awk '{sub(/[^.]*[.]/, "", $0)} 1'
# Extension (last-2): 'tar.gz'
echo "$f" | awk -F'[.]' '{print $(NF-1)"."$NF}'
# Basename : 'file'
echo "$f" | awk '{gsub(/.*[/]|[.].*/, "", $0)} 1'
# Basename-extended : 'file.1.0.1.tar'
echo "$f" | awk '{gsub(/.*[/]|[.]{1}[^.]+$/, "", $0)} 1'
# Path : '/path/to/complex/'
echo "$f" | awk '{match($0, /.*[/]/, a); print a[0]}'
# or
echo "$f" | grep -Eo '.*[/]'
# Folder (containing the file) : 'complex'
echo "$f" | awk -F'/' '{$1=""; print $(NF-1)}'
# Version : '1.0.1'
# Defined as 'number.number' or 'number.number.number'
echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?'
# Version - major : '1'
echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f1
# Version - minor : '0'
echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f2
# Version - patch : '1'
echo "$f" | grep -Eo '[0-9]+[.]+[0-9]+[.]?[0-9]?' | cut -d. -f3
# All Components : "path to complex file 1 0 1 tar gz"
echo "$f" | awk -F'[/.]' '{$1=""; print $0}'
# Is absolute : True (exit-code : 0)
# Return true if it is an absolute path (starting with '/' or '~/'
echo "$f" | grep -q '^[/]\|^~/'
Wszystkie przypadki użycia używają oryginalnej pełnej ścieżki jako danych wejściowych, bez zależności od wyników pośrednich.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-16 09:02:52
[zmieniono z jednowierszowej na ogólną funkcję bash , zachowanie zgodne z narzędziami dirname
i basename
; Dodano uzasadnienie.]
The akceptowana odpowiedź działa dobrze w typowych przypadkach , Ale zawodzi w edge } przypadkach , a mianowicie:
- dla nazw plików bez rozszerzenia (wywołanych przyrostkiem w pozostałej części odpowiedzi),
extension=${filename##*.}
zwraca nazwę pliku wejściowego zamiast pustego łańcucha. -
extension=${filename##*.}
nie zawiera inicjału.
, wbrew konwencji.- ślepe poprzedzanie
.
nie zadziała dla nazw plików bez sufiksu.
- ślepe poprzedzanie
-
filename="${filename%.*}"
będzie pustym łańcuchem znaków, jeśli nazwa pliku wejściowego zaczyna się od.
i nie zawiera dalszych znaków.
(np..bash_profile
) - wbrew konwencji.
---------
Tak więc złożoność rozwiązania obejmującego wszystkie przypadki brzegowe wymaga funkcji - zobacz jej definicja poniżej; to może zwrócić wszystkie Składniki ścieżki.
Przykładowe wywołanie:
splitPath '/etc/bash.bashrc' dir fname fnameroot suffix
# -> $dir == '/etc'
# -> $fname == 'bash.bashrc'
# -> $fnameroot == 'bash'
# -> $suffix == '.bashrc'
Zauważ, że argumenty po ścieżce wejściowej są dowolnie wybierane, pozycyjne zmienne nazwy .
Aby pominąć zmienne, które nie są interesujące, przed tymi, które są, określ _
(aby użyć zmiennej throw-away $_
) lub ''
; np. aby wyodrębnić tylko root i rozszerzenie nazwy pliku, użyj splitPath '/etc/bash.bashrc' _ _ fnameroot extension
.
# SYNOPSIS
# splitPath path varDirname [varBasename [varBasenameRoot [varSuffix]]]
# DESCRIPTION
# Splits the specified input path into its components and returns them by assigning
# them to variables with the specified *names*.
# Specify '' or throw-away variable _ to skip earlier variables, if necessary.
# The filename suffix, if any, always starts with '.' - only the *last*
# '.'-prefixed token is reported as the suffix.
# As with `dirname`, varDirname will report '.' (current dir) for input paths
# that are mere filenames, and '/' for the root dir.
# As with `dirname` and `basename`, a trailing '/' in the input path is ignored.
# A '.' as the very first char. of a filename is NOT considered the beginning
# of a filename suffix.
# EXAMPLE
# splitPath '/home/jdoe/readme.txt' parentpath fname fnameroot suffix
# echo "$parentpath" # -> '/home/jdoe'
# echo "$fname" # -> 'readme.txt'
# echo "$fnameroot" # -> 'readme'
# echo "$suffix" # -> '.txt'
# ---
# splitPath '/home/jdoe/readme.txt' _ _ fnameroot
# echo "$fnameroot" # -> 'readme'
splitPath() {
local _sp_dirname= _sp_basename= _sp_basename_root= _sp_suffix=
# simple argument validation
(( $# >= 2 )) || { echo "$FUNCNAME: ERROR: Specify an input path and at least 1 output variable name." >&2; exit 2; }
# extract dirname (parent path) and basename (filename)
_sp_dirname=$(dirname "$1")
_sp_basename=$(basename "$1")
# determine suffix, if any
_sp_suffix=$([[ $_sp_basename = *.* ]] && printf %s ".${_sp_basename##*.}" || printf '')
# determine basename root (filemane w/o suffix)
if [[ "$_sp_basename" == "$_sp_suffix" ]]; then # does filename start with '.'?
_sp_basename_root=$_sp_basename
_sp_suffix=''
else # strip suffix from filename
_sp_basename_root=${_sp_basename%$_sp_suffix}
fi
# assign to output vars.
[[ -n $2 ]] && printf -v "$2" "$_sp_dirname"
[[ -n $3 ]] && printf -v "$3" "$_sp_basename"
[[ -n $4 ]] && printf -v "$4" "$_sp_basename_root"
[[ -n $5 ]] && printf -v "$5" "$_sp_suffix"
return 0
}
test_paths=(
'/etc/bash.bashrc'
'/usr/bin/grep'
'/Users/jdoe/.bash_profile'
'/Library/Application Support/'
'readme.new.txt'
)
for p in "${test_paths[@]}"; do
echo ----- "$p"
parentpath= fname= fnameroot= suffix=
splitPath "$p" parentpath fname fnameroot suffix
for n in parentpath fname fnameroot suffix; do
echo "$n=${!n}"
done
done
Kod testowy, który ćwiczy funkcja:
test_paths=(
'/etc/bash.bashrc'
'/usr/bin/grep'
'/Users/jdoe/.bash_profile'
'/Library/Application Support/'
'readme.new.txt'
)
for p in "${test_paths[@]}"; do
echo ----- "$p"
parentpath= fname= fnameroot= suffix=
splitPath "$p" parentpath fname fnameroot suffix
for n in parentpath fname fnameroot suffix; do
echo "$n=${!n}"
done
done
Oczekiwane wyjście-zwróć uwagę na przypadki krawędzi:
- nazwa pliku bez przyrostka
- nazwa pliku zaczynająca się od
.
(Nie uważany za początek sufiksu)
Nie jest to jednak możliwe, ponieważ nie jest to możliwe.]}
- ścieżka wejściowa, która jest tylko nazwą pliku (
.
jest zwracana jako ścieżka nadrzędna) - nazwa pliku, który ma więcej niż
.
-przedrostek tokena (tylko ostatni jest uważany za sufiks):
----- /etc/bash.bashrc
parentpath=/etc
fname=bash.bashrc
fnameroot=bash
suffix=.bashrc
----- /usr/bin/grep
parentpath=/usr/bin
fname=grep
fnameroot=grep
suffix=
----- /Users/jdoe/.bash_profile
parentpath=/Users/jdoe
fname=.bash_profile
fnameroot=.bash_profile
suffix=
----- /Library/Application Support/
parentpath=/Library
fname=Application Support
fnameroot=Application Support
suffix=
----- readme.new.txt
parentpath=.
fname=readme.new.txt
fnameroot=readme.new
suffix=.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:43
Myślę, że jeśli potrzebujesz tylko nazwy pliku, możesz spróbować tego:
FULLPATH=/usr/share/X11/xorg.conf.d/50-synaptics.conf
# Remove all the prefix until the "/" character
FILENAME=${FULLPATH##*/}
# Remove all the prefix until the "." character
FILEEXTENSION=${FILENAME##*.}
# Remove a suffix, in our case, the filename. This will return the name of the directory that contains this file.
BASEDIRECTORY=${FULLPATH%$FILENAME}
echo "path = $FULLPATH"
echo "file name = $FILENAME"
echo "file extension = $FILEEXTENSION"
echo "base directory = $BASEDIRECTORY"
I to wszystko =D.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 17:00:14
Najmniejsze i najprostsze rozwiązanie (w jednej linii) to:
$ file=/blaabla/bla/blah/foo.txt
echo $(basename ${file%.*})
foo
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-22 14:39:16
Możesz wymusić wycięcie, aby wyświetlić wszystkie pola i kolejne dodając -
do numeru pola.
NAME=`basename "$FILE"`
EXTENSION=`echo "$NAME" | cut -d'.' -f2-`
Więc jeśli plik jest eth0.pcap.gz
, rozszerzenie będzie pcap.gz
Używając tej samej logiki, możesz również pobrać nazwę pliku używając ' - ' z wyciętym w następujący sposób:
NAME=`basename "$FILE" | cut -d'.' -f-1`
Działa to nawet dla nazw plików, które nie mają rozszerzenia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-30 16:23:11
Ok więc jeśli dobrze rozumiem, problem polega na tym, jak zdobyć nazwę i pełne rozszerzenie pliku, który ma wiele rozszerzeń, np. stuff.tar.gz
.
To działa dla mnie:
fullfile="stuff.tar.gz"
fileExt=${fullfile#*.}
fileName=${fullfile%*.$fileExt}
To daje stuff
jako nazwę pliku i .tar.gz
jako rozszerzenie. Działa dla dowolnej liczby rozszerzeń, w tym 0. Mam nadzieję, że to pomoże każdemu, kto ma ten sam problem =)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-02 10:26:40
Magiczne rozpoznawanie plików
Oprócz wielu dobrych odpowiedzi na to pytanie o przepełnienie stosu chciałbym dodać:
Pod Linuksem i innymi unixenami istnieje magiczne polecenie o nazwie file
, które wykrywa typ pliku analizując niektóre pierwsze bajty pliku. Jest to bardzo stare narzędzie, początkowo używane dla serwerów wydruku (jeśli nie zostało stworzone dla... Nie jestem tego pewien).
file myfile.txt
myfile.txt: UTF-8 Unicode text
file -b --mime-type myfile.txt
text/plain
Rozszerzenia standardów można znaleźć w /etc/mime.types
(na moim Debianie GNU / Linux desktop. Zob. man file
i man mime.types
. Być może musisz zainstalować pakiety file
utility i mime-support
):
grep $( file -b --mime-type myfile.txt ) </etc/mime.types
text/plain asc txt text pot brf srt
Możesz utworzyć funkcję bash do określania WŁAŚCIWEGO rozszerzenia. Jest mała (nie idealna) próbka:
file2ext() {
local _mimetype=$(file -Lb --mime-type "$1") _line _basemimetype
case ${_mimetype##*[/.-]} in
gzip | bzip2 | xz | z )
_mimetype=${_mimetype##*[/.-]}
_mimetype=${_mimetype//ip}
_basemimetype=$(file -zLb --mime-type "$1")
;;
stream )
_mimetype=($(file -Lb "$1"))
[ "${_mimetype[1]}" = "compressed" ] &&
_basemimetype=$(file -b --mime-type - < <(
${_mimetype,,} -d <"$1")) ||
_basemimetype=${_mimetype,,}
_mimetype=${_mimetype,,}
;;
executable ) _mimetype='' _basemimetype='' ;;
dosexec ) _mimetype='' _basemimetype='exe' ;;
shellscript ) _mimetype='' _basemimetype='sh' ;;
* )
_basemimetype=$_mimetype
_mimetype=''
;;
esac
while read -a _line ;do
if [ "$_line" == "$_basemimetype" ] ;then
[ "$_line[1]" ] &&
_basemimetype=${_line[1]} ||
_basemimetype=${_basemimetype##*[/.-]}
break
fi
done </etc/mime.types
case ${_basemimetype##*[/.-]} in
executable ) _basemimetype='' ;;
shellscript ) _basemimetype='sh' ;;
dosexec ) _basemimetype='exe' ;;
* ) ;;
esac
[ "$_mimetype" ] && [ "$_basemimetype" != "$_mimetype" ] &&
printf ${2+-v} $2 "%s.%s" ${_basemimetype##*[/.-]} ${_mimetype##*[/.-]} ||
printf ${2+-v} $2 "%s" ${_basemimetype##*[/.-]}
}
Ta funkcja może ustawić zmienną Bash, która może być użyta później:
(to jest inspirowane @Petesh right answer):
filename=$(basename "$fullfile")
filename="${filename%.*}"
file2ext "$fullfile" extension
echo "$fullfile -> $filename . $extension"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 17:04:11
$ F = "text file.test.txt"
$ echo ${F/*./}
txt
Ta funkcja obsługuje wiele kropek i spacji w nazwie pliku, Jednak jeśli nie ma rozszerzenia, zwraca samą nazwę pliku. Łatwo jednak sprawdzić, czy nazwa pliku i rozszerzenie są takie same.
Oczywiście ta metoda nie działa .smoła.pliki gz. Można to jednak przeprowadzić w dwuetapowym procesie. Jeśli rozszerzeniem jest gz, sprawdź ponownie, czy istnieje również rozszerzenie tar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 13:58:28
Używam następującego skryptu
$ echo "foo.tar.gz"|rev|cut -d"." -f3-|rev
foo
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-22 12:56:10
Jak wyodrębnić nazwę pliku i rozszerzenie w ryby:
function split-filename-extension --description "Prints the filename and extension"
for file in $argv
if test -f $file
set --local extension (echo $file | awk -F. '{print $NF}')
set --local filename (basename $file .$extension)
echo "$filename $extension"
else
echo "$file is not a valid file"
end
end
end
Caveats: dzieli się na ostatnią kropkę, co działa dobrze dla nazw plików z kropkami w nich, ale nie dobrze dla rozszerzeń z kropkami w nich. Zobacz przykład poniżej.
Użycie:
$ split-filename-extension foo-0.4.2.zip bar.tar.gz
foo-0.4.2 zip # Looks good!
bar.tar gz # Careful, you probably want .tar.gz as the extension.
Są na to chyba lepsze sposoby. Zapraszam do edycji mojej odpowiedzi, aby ją poprawić.
Jeśli masz do czynienia z ograniczonym zestawem rozszerzeń i znasz je wszystkie, spróbuj to:
switch $file
case *.tar
echo (basename $file .tar) tar
case *.tar.bz2
echo (basename $file .tar.bz2) tar.bz2
case *.tar.gz
echo (basename $file .tar.gz) tar.gz
# and so on
end
To nie ma zastrzeżenie jako pierwszy przykład, ale musisz zająć się każdą sprawą, więc może być bardziej żmudne w zależności od tego, ile rozszerzeń możesz się spodziewać.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-30 21:41:03
Oto kod z AWK . Można to zrobić prościej. Ale nie jestem dobry w AWK.
filename$ ls
abc.a.txt a.b.c.txt pp-kk.txt
filename$ find . -type f | awk -F/ '{print $2}' | rev | awk -F"." '{$1="";print}' | rev | awk 'gsub(" ",".") ,sub(".$", "")'
abc.a
a.b.c
pp-kk
filename$ find . -type f | awk -F/ '{print $2}' | awk -F"." '{print $NF}'
txt
txt
txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 17:00:58
Prosta odpowiedź:
Aby rozszerzyć na zmienne POSIX odpowiadają , zauważ, że możesz zrobić więcej ciekawych wzorców. Tak więc w przypadku opisanym tutaj, możesz po prostu zrobić to:
tar -zxvf $1
cd ${1%.tar.*}
To odetnie ostatnie wystąpienie .smoła.
Bardziej ogólnie, jeśli chcesz usunąć ostatnie wystąpienie .
${1.*.*}
Powinno działać dobrze.
[[2]] Link powyższa odpowiedź wygląda na martwego. Oto świetne wyjaśnienie kilku manipulacji łańcuchami, które możesz zrobić bezpośrednio w Bash, z TLDP .Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 17:07:49
Budowanie z Petesh odpowiedź, jeśli potrzebna jest tylko nazwa pliku, zarówno ścieżka, jak i rozszerzenie mogą być usunięte w jednej linii,
filename=$(basename ${fullname%.*})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:45
Po prostu użyj ${parameter%word}
W Twoim przypadku:
${FILE%.*}
Jeśli chcesz go przetestować, wykonaj następujące czynności i po prostu usuń rozszerzenie:
FILE=abc.xyz; echo ${FILE%.*};
FILE=123.abc.xyz; echo ${FILE%.*};
FILE=abc; echo ${FILE%.*};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-14 15:48:43
Oparty w dużej mierze na doskonałych, a zarazem pełnych losowych, użytecznych bashismach -a także innych odpowiedzi na to / inne pytania / "ten cholerny internet"... I owinął to wszystko w trochę, nieco bardziej zrozumiałe, wielokrotnego użytku Funkcja dla mojego (lub Twój) .bash_profile
, która zajmuje się tym, co (uważam) powinna być bardziej solidna wersja dirname
/basename
/ co masz ..
function path { SAVEIFS=$IFS; IFS="" # stash IFS for safe-keeping, etc.
[[ $# != 2 ]] && echo "usage: path <path> <dir|name|fullname|ext>" && return # demand 2 arguments
[[ $1 =~ ^(.*/)?(.+)?$ ]] && { # regex parse the path
dir=${BASH_REMATCH[1]}
file=${BASH_REMATCH[2]}
ext=$([[ $file = *.* ]] && printf %s ${file##*.} || printf '')
# edge cases for extesionless files and files like ".nesh_profile.coffee"
[[ $file == $ext ]] && fnr=$file && ext='' || fnr=${file:0:$((${#file}-${#ext}))}
case "$2" in
dir) echo "${dir%/*}"; ;;
name) echo "${fnr%.*}"; ;;
fullname) echo "${fnr%.*}.$ext"; ;;
ext) echo "$ext"; ;;
esac
}
IFS=$SAVEIFS
}
Przykłady użycia...
SOMEPATH=/path/to.some/.random\ file.gzip
path $SOMEPATH dir # /path/to.some
path $SOMEPATH name # .random file
path $SOMEPATH ext # gzip
path $SOMEPATH fullname # .random file.gzip
path gobbledygook # usage: -bash <path> <dir|name|fullname|ext>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-27 02:18:45
Z powyższych odpowiedzi wynika, że najkrótszy z nich naśladuje Pythona
file, ext = os.path.splitext(path)
Zakładając, że Twój plik naprawdę ma rozszerzenie, to
EXT="${PATH##*.}"; FILE=$(basename "$PATH" .$EXT)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-20 17:04:50
Jeśli chcesz również zezwolić na puste rozszerzenia, jest to najkrótsze, jakie mogłem wymyślić:
echo 'hello.txt' | sed -r 's/.+\.(.+)|.*/\1/' # EXTENSION
echo 'hello.txt' | sed -r 's/(.+)\..+|(.*)/\1\2/' # FILENAME
Pierwsza linia wyjaśniona: pasuje do ścieżki.EXT lub cokolwiek i zastępuje go EXT. Jeśli cokolwiek zostało dopasowane, Grupa ext nie jest przechwytywana.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-17 16:47:03
W celu uĺźytecznoĺ "Ci katalogu (w przypadku gdy plik lokalny bez Ĺ" cieĺźki jest podany jako input) wykonaĹ ' em nastÄ ™ pujÄ ... ce:
# Substring from 0 thru pos of filename
dir="${fullpath:0:${#fullpath} - ${#filename}}"
if [[ -z "$dir" ]]; then
dir="./"
fi
To pozwala zrobić coś użytecznego, na przykład dodać sufiks do nazwy podstawowej pliku wejściowego jako:
outfile=${dir}${base}_suffix.${ext}
testcase: foo.bar
dir: "./"
base: "foo"
ext: "bar"
outfile: "./foo_suffix.bar"
testcase: /home/me/foo.bar
dir: "/home/me/"
base: "foo"
ext: "bar"
outfile: "/home/me/foo_suffix.bar"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-09 00:05:19
Możesz użyć
sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-
Aby uzyskać nazwę pliku i
sed 's/^/./' | rev | cut -d. -f1 | rev
Aby uzyskać rozszerzenie.
Przypadek testowy:
echo "filename.gz" | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-
echo "filename.gz" | sed 's/^/./' | rev | cut -d. -f1 | rev
echo "filename" | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-
echo "filename" | sed 's/^/./' | rev | cut -d. -f1 | rev
echo "filename.tar.gz" | sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-
echo "filename.tar.gz" | sed 's/^/./' | rev | cut -d. -f1 | rev
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-22 20:24:16
Oto algorytm, którego użyłem do znalezienia nazwy i rozszerzenia pliku, gdy napisałem skrypt Bash, aby nazwy były unikalne, gdy nazwy są skonfliktowane w odniesieniu do obudowy.
#! /bin/bash
#
# Finds
# -- name and extension pairs
# -- null extension when there isn't an extension.
# -- Finds name of a hidden file without an extension
#
declare -a fileNames=(
'.Montreal'
'.Rome.txt'
'Loundon.txt'
'Paris'
'San Diego.txt'
'San Francisco'
)
echo "Script ${0} finding name and extension pairs."
echo
for theFileName in "${fileNames[@]}"
do
echo "theFileName=${theFileName}"
# Get the proposed name by chopping off the extension
name="${theFileName%.*}"
# get extension. Set to null when there isn't an extension
# Thanks to mklement0 in a comment above.
extension=$([[ "$theFileName" == *.* ]] && echo ".${theFileName##*.}" || echo '')
# a hidden file without extenson?
if [ "${theFileName}" = "${extension}" ] ; then
# hidden file without extension. Fixup.
name=${theFileName}
extension=""
fi
echo " name=${name}"
echo " extension=${extension}"
done
Próba.
$ config/Name\&Extension.bash
Script config/Name&Extension.bash finding name and extension pairs.
theFileName=.Montreal
name=.Montreal
extension=
theFileName=.Rome.txt
name=.Rome
extension=.txt
theFileName=Loundon.txt
name=Loundon
extension=.txt
theFileName=Paris
name=Paris
extension=
theFileName=San Diego.txt
name=San Diego
extension=.txt
theFileName=San Francisco
name=San Francisco
extension=
$
FYI: kompletny program do transliteracji i więcej przypadków testowych można znaleźć tutaj: https://www.dropbox.com/s/4c6m0f2e28a1vxf/avoid-clashes-code.zip?dl=0
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-21 23:25:33