bash - bash中提取文件名和扩展名

  显示原文与译文双语对照的内容

我想分别获取文件名( 没有扩展名) 和扩展名。

到目前为止我发现的最佳解决方案是:


NAME=`echo"$FILE" | cut -d'.' -f1`
EXTENSION=`echo"$FILE" | cut -d'.' -f2`

这是错误的,因为如果文件名包含多个"。"字符,它将不起作用。 让我们说,如果我有 a.b.js 它将考虑 b.js, 代替 a.bjs

它可以很容易地在 python 中完成


file, ext = os.path.splitext(path)

但我宁愿不为此而激发一个 python 解释器。

任何更好的想法?

时间:

首先,获取不带路径的文件:


filename=$(basename"$fullfile")
extension="${filename##*.}"
filename="${filename%.*}"

或者,你可以专注于路径的最后一个'/'而不是'。',即使你有不可预知的文件扩展名也可以这样做:


filename="${fullfile##*/}"


~% FILE="example.tar.gz"
~% echo"${FILE%%.*}"
example
~% echo"${FILE%.*}"
example.tar
~% echo"${FILE#*.}"
tar.gz
~% echo"${FILE##*.}"
gz

有关更多信息,请参见Bash手册中的外壳参数扩展

你可以使用POSIX变量的魔力:


bash-3.2$ FILENAME=somefile.tar.gz
bash-3.2$ echo ${FILENAME%%.*}
somefile
bash-3.2$ echo ${FILENAME%.*}
somefile.tar


这里有一个警告,如果你的文件名是 ./somefile.tar.gz的形式,echo ${FILENAME%%.*} 将greedily删除到 .的最长的匹配,你会得到空字符串。

( 你可以使用一个临时变量来解决这个问题:


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

通常你已经知道扩展,所以你可能希望使用:


basename filename. extension

例如:


basename/path/to/dir/filename.txt. txt

我们得到了

 
filename

 

如果文件没有扩展名,或者没有文件名,这似乎不起作用。 这是我所使用的功能;它只使用内置的( 但并非全部) 病理文件名。


#!/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:ntdir = "$dir"ntbase = "$base"ntext = "$ext""
done

下面是一些计量经济学:

$ 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 =""

你可以使用 basename

例如:


$ basename foo-bar.tar.gz. tar.gz
foo-bar

你需要提供:删除扩展应,然而如果你总是执行 tar-z 然后你知道 .tar.gz 扩展。

这应该符合你的要求:


tar -zxvf $1
cd $(basename $1. tar.gz)

你可以使用 cut 命令删除最后两个扩展名( ".tar.gz" 部件):


$ echo"foo.tar.gz" | cut -d'.' --complement -f2-
foo


就像 Clayton 。休斯在评论中提到的,这对于问题中的实际例子不起作用。 因此,我建议使用 sed 和扩展 正规表达式,如下所示:


$ echo"mpc-1.0.1.tar.gz" | sed -r 's/.[[:alnum:]]+.[[:alnum:]]+$//'
mpc-1.0.1

它通过无条件删除最后两个( alpha-numeric ) 扩展来工作。

[Updated again after comment from Anders Lindahl ]

Mellen在博客帖子中写入评论:

使用 Bash,也有 ${file%.*} 来获取文件名,而不用扩展和 ${file##*.} 来获得扩展。 也就是说


file="thisfile.txt"
echo"filename: ${file%.*}"
echo"extension: ${file##*.}"

输出:


filename: thisfile
extension: txt


pax> echo a.b.js | sed 's/.[^.]*$//'
a.b
pax> echo a.b.js | sed 's/^.*.//'
js

工作正常,所以你可以只使用:


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

顺便说一句,命令的工作方式如下。

NAME sed字符串替代 . 字符后跟任意数量的非"。"行结束字符,一无所有( 例如 。,它删除从结束的最后"。"线,包容)。 这基本上是一个使用 正规表达式 诡计non-greedy替换。

EXTENSION sed字符串替代一个任意数量的字符后跟"。"字符开始的时候,没有( 例如 。,它消除了从线的开始到最后一个点,包容性) 。 这是一个贪婪替换,它是默认动作。

我认为如果你只需要文件名,你可以尝试:


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"

这就是 =D 。

...