我需要创建文件列表(播放列表)以便在 Docker 容器中使用它。所以文件在主机系统上的路径不是安装路径。现在我尝试解决这个问题,但遇到了一些麻烦。
这是我的脚本,我想在其中添加替换
tdir="/mountingpoint"
readarray -d $'\0' listing < <(find "${fdir}"/*.mp3 -print0)
#for mixing up and write to file
listing=( $(shuf -e "${listing[@]}") )
printf "%s\n" "${listing[@]}" > "playlist.m3u"
一种常见的方法应该是使用,sed
但我在将东西放在一起时遇到了一些麻烦。我想我必须将脚本修改为类似的内容readarray -d $'\0' listing < <(find "${fdir}"/"${d}"/ -name "*.mp3" -print0 -exec sed -i "s/"$fdir"/"$tdir"/" {} \;)
,但这会导致错误 sed: -e expression #1, char 9: unknown option to `s'
我认为目录名称中的斜杠会导致此错误。但我也尝试用文件夹名称替换变量来检查结果,但什么也没发生(除了更长的运行时间之外)。 Nothing 意味着输出文件中没有替换。
我希望有人能解决我糟糕的英语问题并提示我哪里做错了。多谢
答案1
作为@伊卡洛斯有指出,该-exec
选项在这里没有意义 - 您想要将 sed 替换应用于空分隔文件名字,使用不太可能出现在这些名称中的 sed 模式分隔符:
find "${fdir}/${d}" -name '*.mp3' -print0 | sed -z "s:$fdir:$tdir:"
恕我直言,没有理由不在管道内包含洗牌:
find "${fdir}/${d}" -name '*.mp3' -print0 | sed -z "s:$fdir:$tdir:" | shuf -z
例如给出
~$ find . -name '*.mp3'
./dir/1.mp3
./dir/2.mp3
./dir/3.mp3
./dir/4.mp3
./dir/5.mp3
然后
~$ fdir=./dir; tdir='./new/dir'
~$ readarray -t -d '' listing < <(find . -name '*.mp3' -print0 | sed -z "s:$fdir:$tdir:" | shuf -z)
~$ printf '%s\n' "${listing[@]}"
./new/dir/3.mp3
./new/dir/1.mp3
./new/dir/4.mp3
./new/dir/2.mp3
./new/dir/5.mp3
答案2
用zsh
而不是bash
:
() {print -rC1 -- $tdir/$^@} $fdir/*.mp3(Noe['REPLY=$RANDOM']:t)
或者假设既不$fdir
也不$tdir
包含:
字符:
print -rC1 -- $fdir/*.mp3(Noe['REPLY=$RANDOM']:s:$fdir:$tdir)
使用bash
4.4+ 和 GNU shuf
(或sort -zR
),您始终可以执行以下操作:
print0() { [ "$#" -eq 0 ] || printf '%s\0' "$@"; }
println() { [ "$#" -eq 0 ] || printf '%s\n' "$@"; }
readarray -td '' listing < <(
shopt -s nullglob
cd -P -- "$fdir" && print0 *.mp3 | shuf -z)
println "${listing[@]/#/$tdir}"
或者:
print0() { [ "$#" -eq 0 ] || printf '%s\0' "$@"; }
println() { [ "$#" -eq 0 ] || printf '%s\n' "$@"; }
readarray -td '' listing < <(
shopt -s nullglob
print0 "$fdir"/*.mp3 | shuf -z)
println "${listing[@]/#"$fdir"/$tdir}"
作为等价物。