在根文件夹中,我有一个包含一些 mp3 文件的子文件夹结构。我想将所有子文件夹和 mp3 文件复制到 sd 卡,以便 mp3 播放器读取。简单地将整个根文件夹复制到卡上会打乱 mp3 文件的顺序。此问题已在互联网上有记录。一种解决方案是使用 rsync,这对我来说不起作用 - 另一种解决方案是一个接一个地复制文件,这样顺序就适合我的播放器。 因此,我编写了一个 bash 脚本来遍历我的子文件夹结构,在 SD 卡上创建一些子文件夹并将 mp3 文件复制到其中。由于我的子文件夹结构是随机的,我决定编写一个递归函数,在每个子文件夹中调用,如下所示:
ScanKo ()
{
cd "$1"
for i in *
do
if [[ -d "$i" ]]
then
mkdir -p "$2/$i"
ScanKo "$1/$i" "$2/$i"
elif [[ "${i##*.}" = "mp3" ]]
then
cp "$1/$i" "$2/$i"
fi
done
}
ScanKo "/home/monkey/source_root/" "/media/stick/destiny_root/"
函数 ScanKo 获取两个参数:源根文件夹和目标根文件夹。我 cd 进入源文件夹并使用 for 循环扫描所有内容。如果我点击一个子文件夹,我会在目标点(SD 卡)上创建这个子文件夹,并以子文件夹作为参数再次调用该函数。如果我点击一个 mp3 文件,我会将它复制到命运中。它仅在理论上有效。看起来,一旦子函数被调用,bash 就失去了它的上下文。
我通过递归过程实施相同的方法解决了这个问题。名为“sdMachen”的进程的相应 bash 脚本如下所示:
cd "$1"
for i in *
do
if [[ -d "$i" ]]
then
mkdir -p "$2/$i"
bash "$3/${0##*/}" "$1/$i" "$2/$i" "$3"
elif [[ "${i##*.}" = "mp3" ]]
then
cp "$1/$i" "$2/$i"
fi
done
我在命令行上使用三个参数调用脚本:
bash sdMachen "/home/monkey/source_root/" "/media/stick/destiny_root/" "$(pwd)"
我需要第三个参数,这样我就可以返回sdMachen所在的位置。部分
需要“$3/${0##*/}”
,以便每次都能找到正确的 bash 脚本。基本上相当于
/脚本所在文件夹/sdMachen
它适用于递归过程 - 但为什么它不适用于递归 bash 函数?
由于您使用的是 Bash,因此您可以受益于其
globstar
选项,将所有子目录作为平面列表进行使用:
#!/usr/bin/env bash
ScanKo() {
local srcDir=${1:?}
local dstDir=${2:?}
# Validates arguments
[ -d "$srcDir" ] && [ -d "$dstDir" ] || exit 2
# Saves globstar and nullglob options
if shopt -q globstar; then local gs=s; else local gs=u; fi
if shopt -q nullglob; then local ng=s; else local ng=u; fi
# Sets globstar and nullglob options
shopt -s globstar nullglob
# Iterates source directory hierarchy with globstar **
for dir in "$srcDir/"**/; do
mkdir -p -- "${dstDir%/}${dir##$srcDir}"
done
# Restores globstar and nullglob as they where
shopt "-$gs" globstar
shopt "-$ng" nullglob
}
ScanKo "$@"