我想分别获取文件名(没有扩展名)和扩展名。
我到目前为止找到的最佳解决方案是:
NAME =echo“$ FILE”|切-d'。' -f1EXTENSION =echo“$ FILE”|切-d'。' -f2
echo“$ FILE”|切-d'。' -f1
echo“$ FILE”|切-d'。' -f2
这个
最小和最简单的解决方案(单线)是:
$ file=/blaabla/bla/blah/foo.txt echo $(basename ${file%.*}) # foo
您可以使用
sed 's/^/./' | rev | cut -d. -f2- | rev | cut -c2-
获取文件名和
sed 's/^/./' | rev | cut -d. -f1 | rev
得到扩展。
测试用例:
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
恕我直言已经给出了最好的解决方案(使用shell参数扩展),目前是最好的解决方案。
然而,我添加了一个只使用哑命令,这是没有效率,没有人认真应该使用:
FILENAME=$(echo $FILE | cut -d . -f 1-$(printf $FILE | tr . '\n' | wc -l)) EXTENSION=$(echo $FILE | tr . '\n' | tail -1)
添加 的 纯娱乐 强> :-)
从上面的答案,最短的oneliner模仿Python的
file, ext = os.path.splitext(path)
假设您的文件确实有扩展名,是
EXT="${PATH##*.}"; FILE=$(basename "$PATH" .$EXT)
你可以使用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%%.*} 会贪婪地删除最长的匹配 . 而且你有空字符串。
./somefile.tar.gz
echo ${FILENAME%%.*}
.
(您可以使用临时变量解决此问题:
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
如何提取文件名和扩展名 的 鱼 强> :
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
这样做 的 不 强> 作为第一个例子有警告,但你必须处理每个案例,因此根据你可以期望的扩展数量,它可能会更加繁琐。
通常您已经知道扩展名,因此您可能希望使用:
basename filename .extension
例如:
basename /path/to/dir/filename.txt .txt
我们得到了
filename
我使用以下脚本
$ echo "foo.tar.gz"|rev|cut -d"." -f3-|rev foo
基本上基于@ mklement0的优秀,充满了随机,有用 bash化 - 以及这个/其他问题/“互联网”的其他答案......我把它全部包裹起来,稍微易于理解,可重复使用 功能 为我(或你的) .bash_profile 照顾(我认为)应该是一个更强大的版本 dirname / basename / 你有什么 ..
.bash_profile
dirname
basename
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 }
用法示例......
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>
$ F = "text file.test.txt" $ echo ${F/*./} txt
这适用于文件名中的多个点和空格,但是如果没有扩展名,则返回文件名本身。虽然容易检查;只测试文件名和扩展名是否相同。
当然,这种方法不适用于.tar.gz文件。但是,这可以通过两个步骤处理。如果扩展名是gz,则再次检查以查看是否还有tar扩展名。
以下是一些替代建议(主要是在 awk ),包括一些高级用例,如提取软件包的版本号。
awk
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 '^[/]\|^~/'
所有用例都使用原始完整路径作为输入,而不依赖于中间结果。
为了使dir更有用(在没有路径的本地文件被指定为输入的情况下)我做了以下事情:
# Substring from 0 thru pos of filename dir="${fullpath:0:${#fullpath} - ${#filename}}" if [[ -z "$dir" ]]; then dir="./" fi
这允许您执行一些有用的操作,例如为输入文件basename添加后缀:
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"
您可以强制剪切以显示所有字段和后续添加的字段 - 到场号。
-
NAME=`basename "$FILE"` EXTENSION=`echo "$NAME" | cut -d'.' -f2-`
所以,如果FILE是 eth0.pcap.gz ,EXTENSION将是 pcap.gz
eth0.pcap.gz
pcap.gz
使用相同的逻辑,您还可以使用带有cut的' - '来获取文件名,如下所示:
NAME=`basename "$FILE" | cut -d'.' -f-1`
这适用于没有任何扩展名的文件名。
建设自 Petesh 回答,如果只需要文件名, 路径和扩展都可以在一行中剥离,
filename=$(basename ${fullname%.*})
简单地使用 ${parameter%word}
${parameter%word}
在你的情况下:
${FILE%.*}
如果您想测试它,以下所有工作,只需删除扩展名:
FILE=abc.xyz; echo ${FILE%.*}; FILE=123.abc.xyz; echo ${FILE%.*}; FILE=abc; echo ${FILE%.*};