如何从 bash 获取文件扩展名?这是我尝试过的:
filename=`basename $filepath`
fileext=${filename##*.}
通过这样做,我可以bz2
从路径中获得扩展/dir/subdir/file.bz2
,但我的路径有问题/dir/subdir/file-1.0.tar.bz2
。
如果可能的话,我更喜欢仅使用 bash 而不使用外部程序的解决方案。
为了清楚地说明我的问题,我正在创建一个 bash 脚本,只需通过单个命令即可提取任何给定的存档extract path_to_file
。如何提取文件由脚本通过查看其压缩或归档类型来确定,可能是 .tar.gz、.gz、.bz2 等。我认为这应该涉及字符串操作,例如,如果我获得扩展名,.gz
那么我应该检查它.tar
之前是否有该字符串.gz
- 如果有,则扩展名应该是.tar.gz
.
答案1
您可以通过仅对文件名进行模式匹配而不是提取扩展名两次来简化问题:
case "$filename" in
*.tar.bz2) bunzip_then_untar ;;
*.bz2) bunzip_only ;;
*.tar.gz) untar_with -z ;;
*.tgz) untar_with -z ;;
*.gz) gunzip_only ;;
*.zip) unzip ;;
*.7z) do something ;;
*) do nothing ;;
esac
答案2
如果文件名为file-1.0.tar.bz2
,则扩展名为bz2
.您用来提取扩展名 ( fileext=${filename##*.}
) 的方法完全有效。
您如何决定扩展名是 or tar.bz2
,而不是bz2
or 0.tar.bz2
?你需要先回答这个问题。然后您就可以找出哪些 shell 命令符合您的规范。
一种可能的规范是扩展名必须以字母开头。这种启发式方法对于一些常见的扩展(例如 )会失败
7z
,最好将其视为特殊情况。这是 bash/ksh/zsh 的实现:basename=$filename; fileext= while [[ $basename = ?*.* && ( ${basename##*.} = [A-Za-z]* || ${basename##*.} = 7z ) ]] do fileext=${basename##*.}.$fileext basename=${basename%.*} done fileext=${fileext%.}
为了 POSIX 可移植性,您需要使用
case
语句进行模式匹配。while case $basename in ?*.*) case ${basename##*.} in [A-Za-z]*|7z) true;; *) false;; esac;; *) false;; esac do …
另一种可能的规范是某些扩展名表示编码并指示需要进一步剥离。这是 bash/ksh/zsh 实现(需要
shopt -s extglob
在 bash 和setopt ksh_glob
zsh 下):basename=$filename fileext= while [[ $basename = ?*.@(bz2|gz|lzma) ]]; do fileext=${basename##*.}.$fileext basename=${basename%.*} done if [[ $basename = ?*.* ]]; then fileext=${basename##*.}.$fileext basename=${basename%.*} fi fileext=${fileext%.}
请注意,这被认为
0
是file-1.0.gz
.
和相关结构位于
${VARIABLE##SUFFIX}
POSIX,因此它们可以在任何非古董 Bourne 风格的 shell 中工作,例如 ash、bash、ksh 或 zsh。
答案3
$ echo "thisfile.txt"|awk -F . '{print $NF}'
对此的评论在这里:http://liquidat.wordpress.com/2007/09/29/short-tip-get-file-extension-in-shell-script/
答案4
有一天我创建了那些棘手的函数:
# args: string how_many
function get_last_letters(){ echo ${1:${#1}-$2:$2}; }
function cut_last_letters(){ echo ${1:0:${#1}-$2}; }
我发现这种简单的方法在很多情况下都非常有用,而不仅仅是在涉及扩展时。
用于检查扩展 -简单可靠
~$ get_last_letters file.bz2 4
.bz2
~$ get_last_letters file.0.tar.bz2 4
.bz2
对于切断延伸:
~$ cut_last_letters file.0.tar.bz2 4
file.0.tar
对于更改扩展名:
~$ echo $(cut_last_letters file.0.tar.bz2 4).gz
file.0.tar.gz
或者,如果您喜欢“方便的功能:
~$ function cut_last_letters_and_add(){ echo ${1:0:${#1}-$2}"$3"; }
~$ cut_last_letters_and_add file.0.tar.bz2 4 .gz
file.0.tar.gz
PS 如果您喜欢这些功能或发现它们有用,请参阅这篇文章:)(并希望发表评论)。