我想分别获取文件名(不带扩展名)和扩展名。
到目前为止,我找到的最佳解决方案是:
NAME=`echo "$FILE" | cut -d'.' -f1`
EXTENSION=`echo "$FILE" | cut -d'.' -f2`
这是错误的,因为如果文件名包含多个,它就不起作用。字符。假设我有a.b.js,它会考虑a和b.js而不是a.b和js。
它可以在Python中用
file, ext = os.path.splitext(path)
但如果可能的话,我不希望仅仅为此启动Python解释器。
有更好的主意吗?
如何在fish中提取文件名和扩展名:
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
注意:在最后一个点上进行拆分,这适用于带有点的文件名,但对于带有点的扩展名不适用。请参见下面的示例。
用法:
$ 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.
也许有更好的方法可以做到这一点。请随意编辑我的答案以改进它。
如果您要处理的扩展有限,并且您了解所有扩展,请尝试以下操作:
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
这并没有第一个例子中的警告,但是你必须处理每一个案例,所以它可能会更加乏味,这取决于你可以预期的扩展数量。
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命令将一个“.”字符后接任意数量的非“.”字,直到行尾,但不包含任何内容(即,从最后的“.”到行尾,包括首尾)。这基本上是一个使用正则表达式技巧的非贪婪替换。
EXTENSION命令将任意数量的字符替换为行开头的“.”字符,而不使用任何字符(即,它删除从行开头到最后一个点的所有内容,包括所有内容)。这是一个贪婪的替代,这是默认操作。
主要基于@mklement0的优秀,充斥着随机、有用的抨击——以及对这个/其他问题/“那该死的互联网”的其他答案。。。我用一个稍微更容易理解的、可重用的函数来概括我(或你)的.bash_profile,它考虑了(我认为)应该是一个更健壮的dirname/basename/what have you。。
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 extensionless 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
}
用法示例。。。
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>