剥离目录路径以获取文件名

剥离目录路径以获取文件名

我正在做的是用 LAME 转换 mp3。我已经编写了一个可以工作的旧脚本,但我想为其添加这种功能 - 不再删除该文件,而是将其保存在一个新的根文件夹中,其中的子目录与使用它已经存在的路径相匹配在。

这是我从互联网上获取的代码,我在脚本中使用它来获取路径:

 c=$FILENAME
 xpath=${c%/*} 
 xbase=${c##*/}
 xfext=${xbase##*.}
 xpref=${xbase%.*}
 path=${xpath}
 pref=${xpref}
 ext=${xfext}

xpathpath我目录结构/home/user/working-root-directory/band-folder/album-name/

使用该技术,我如何编写脚本以将乐队文件夹放入单独的变量中,并将专辑文件夹放入单独的变量中?

然后我可以使用它们来创建新的文件夹,将所有的 mp3 按照乐队专辑的顺序保存到不同的根文件夹中;这样我就不用自己移动它们了,所以下次我运行我的脚本时,我不会再对它们进行重新采样,因为它们不再在工作目录路径/文件夹中,而且为了以防万一,我仍保留我的文件的备份副本。

答案1

当引用$cif by文件名你的意思是文件的完整路径那么这项工作真的非常简单。有几种方法可以做到这一点。

仅使用 POSIX shell glob 和参数扩展,您可以执行以下操作:

c='/home/user/working-root-directory/band-folder/album-name/music-file.mp3'
file=${c##*/}
album=${c#*"${c%/*/"$file"}"/}
band=${c#*"${c%/*/"$album"}"/}
band=${band%%/*} album=${album%%/*}

基本上,它的工作原理是从变量的尾部修剪字符串,然后从变量的头部修剪结果。在最后一行中,尾部任何不需要的残留物都被去除。使用现实世界的数据也许更容易理解。如果您要将上面的代码片段包装在启用的 shell 中set -x,您会看到以下几行的内容打印到stderr

+ c=/home/user/working-root-directory/band-folder/album-name/music-file.mp3
+ file=music-file.mp3
+ album=album-name/music-file.mp3
+ band=band-folder/album-name/music-file.mp3
+ band=band-folder
+ album=album-name

另一种方法是使用 shell 的内部字段分隔符在/边界上分割路径名。

set -f; IFS=/             #disable globbing so as not to gen more filenames
set -- $c                 #set the shell's arg array to split path
shift "$(($#-3))"         #remove all but relevant fields
band=$1 album=$2 file=$3  #assign values

这是更多set -x输出:

+ c=/home/user/working-root-directory/band-folder/album-name/music-file.mp3
+ set -f
+ IFS=/
+ set -- '' home user working-root-directory band-folder album-name music-file.mp3
+ shift 4
+ band=band-folder
+ album=album-name
+ file=music-file.mp3

答案2

我会雇用zsh以下人员来完成这项工作:

$ c='/home/user/working-root-directory/band-folder/album-name/filename.mp3'

$ echo $c:h
/home/user/working-root-directory/band-folder/album-name
$ echo $c:h:h
/home/user/working-root-directory/band-folder
$ echo $c:h:h:h
/home/user/working-root-directory

(...)

$ echo $c:t    
filename.mp3
$ echo $c:h:t
album-name
$ echo $c:h:h:t
band-folder

(...)

如果你必须使用bash生活比较困难,你需要使用临时变量:

$ c='/home/user/working-root-directory/band-folder/album-name/filename.mp3'

$ x1=${c%/*}
$ echo $x1
/home/user/working-root-directory/band-folder/album-name
$ x2=${x1%/*}
$ echo $x2
/home/user/working-root-directory/band-folder

 (...)

$ y1=${c##*/}
$ echo $y1
filename.mp3
$ y2=${x1##*/}
$ echo $y2
album-name
$ y3=${x2##*/}
$ echo $y3
band-folder

(...)

答案3

以前的解决方案对我来说似乎过于复杂。在我看来,以下是最简单的解决方案。

在 bash 中获取文件名字符串的目录名

 dirname "$varcontainingfilename"

要从 bash 中的文件名字符串中获取唯一的文件名,请使用

 basename "$varcontainingfilename"

在此基础上,您应该能够轻松地做您想做的事情。

作为脚本 /a/b/c 执行此 shell 脚本的示例将作为示例

 #!/bin/sh
 set -u
 PATH='/bin:/usr/bin'
 export PATH
 filestring="$1"
 fn=`basename "$filestring"`
 dn=`dirname "$filestring"`
 echo Original File String "$filestring"
 echo Filename is "$fn"
 echo directory is "$dn"
 exit 0

答案4

Zsh 是一个更优雅的解决方案,但如果这不是你的 shell,你可以使用awk

 printf "%s\n" "$path"
/home/user/working-root-directory/band-folder/album-name/music-file.mp3

band=$(awk -F/ '{print $(NF-2)}' <(printf "%s" "$path"))
printf "%s\n" "$band"
band-folder

album=$(awk -F/ '{print $(NF-1)}' <(printf "%s" "$path"))
printf "%s\n" "$album"
album-name

file=$(awk -F/ '{print $NF}' <(printf "%s" "$path"))
printf "%s\n" "$file"
music-file.mp3

相关内容