在将find
结果读入数组时,我希望它们同时排序(mp3,所以按轨道号,这是文件名的第一部分),并认为这样的事情应该做的伎俩:
mp3s=()
while read -r -d $'\0'; do
mp3s+=("$REPLY")
done < <(sort <(find "$mp3Dir" -type f -name '*.mp3' -print0))
但数组中的元素永远不会正确排序(文件名的第一部分是mp3轨道号:01 _...,02 _...,03 _...等)
虽然以下内容完成了工作,但似乎不必要的尴尬:
mp3s=()
while read -r -d $'\0'; do
mp3s+=("$REPLY")
done < <(find "$mp3Dir" -type f -name '*.mp3' -print0)
mp3s=( $(for f in "${mp3s[@]}" ; do
echo "$f"
done | sort) )
必须有一种更简化的方法来完成这项工作,与我在第一个例子中的想法类似,不是吗?我已尝试在sort
命令的两侧阅读find
,使用其众多选项进行排序(-n,-d等),但没有任何运气(到目前为止)。
那么,在最初填充数组时,是否有更有效的方法来合并sort
命令?
答案 0 :(得分:4)
默认情况下,sort
采用换行符分隔的记录。但是,对find
的调用指定了空分隔输出。解决方案是将-z
标志添加到sort
。这告诉sort
期望nul分离的输入并产生nul分离的输出。因此,请尝试:
mp3s=()
while read -r -d $'\0'; do
mp3s+=("$REPLY")
done < <(sort -z <(find "$mp3Dir" -type f -name '*.mp3' -print0))
假设我们有这些mp3文件:
$ find "." -type f -name '*.mp3' -print0
./music1/d b2.mp3./music1/a b1.mp3./music1/a b2.mp3./music1/d b1.mp3./music1/a b3.mp3./music1/d b3.mp3
首先,试试sort
:
$ sort <(find "." -type f -name '*.mp3' -print0)
./music1/d b2.mp3./music1/a b1.mp3./music1/a b2.mp3./music1/d b1.mp3./music1/a b3.mp3./music1/d b3.mp3
文件仍然无序。
现在,试试sort -z
:
$ sort -z <(find "." -type f -name '*.mp3' -print0)
./music1/a b1.mp3./music1/a b2.mp3./music1/a b3.mp3./music1/d b1.mp3./music1/d b2.mp3./music1/d b3.mp3
这些文件现在已按顺序排列。
答案 1 :(得分:4)
在内部进行bash排序的一种方法是使用关联数组并将数据放入键中,而不是值。
declare -A mp3s=()
while IFS= read -r -d ''; do
mp3s[$REPLY]=1
done < <(find "$mp3Dir" -type f -name '*.mp3' -print0)
...然后,迭代值:
for mp3 in "${!mp3s[@]}"; do
printf '%q\n' "$mp3"
done
由于关联数组是bash 4.0中添加的一项功能,请注意3.2中没有此功能(在某些圈子中仍在使用,特别是MacOS)。