替换 readarray 命令中 find 输出的一部分

替换 readarray 命令中 find 输出的一部分

我需要创建文件列表(播放列表)以便在 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)

使用bash4.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}"

作为等价物。

相关内容