我正在做的是用 LAME 转换 mp3。我已经编写了一个可以工作的旧脚本,但我想为其添加这种功能 - 不再删除该文件,而是将其保存在一个新的根文件夹中,其中的子目录与使用它已经存在的路径相匹配在。
这是我从互联网上获取的代码,我在脚本中使用它来获取路径:
c=$FILENAME
xpath=${c%/*}
xbase=${c##*/}
xfext=${xbase##*.}
xpref=${xbase%.*}
path=${xpath}
pref=${xpref}
ext=${xfext}
并xpath
给path
我目录结构/home/user/working-root-directory/band-folder/album-name/
使用该技术,我如何编写脚本以将乐队文件夹放入单独的变量中,并将专辑文件夹放入单独的变量中?
然后我可以使用它们来创建新的文件夹,将所有的 mp3 按照乐队专辑的顺序保存到不同的根文件夹中;这样我就不用自己移动它们了,所以下次我运行我的脚本时,我不会再对它们进行重新采样,因为它们不再在工作目录路径/文件夹中,而且为了以防万一,我仍保留我的文件的备份副本。
答案1
当引用$c
if 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