如何使用命令输出(ls)到其他命令的输入(sox)中?

如何使用命令输出(ls)到其他命令的输入(sox)中?

我有一个包含多个 .wav 文件的文件夹,我试图按顺序连接这些文件,但我认为我对 bash 命令缺乏经验,无法尽可能高效地执行此操作。你看,我不知道如何使用文件内容作为命令的输入:

我以正确的顺序获取所有文件名:

ls *.wav | sort -V > script

脚本:

ep1-s1.wav
ep2-s1.wav
ep3-s1.wav

我在每行后面添加“\”以在命令中使用

lam script -s " \\" > script2

脚本2:

ep1-s1.wav \
ep2-s1.wav \
ep3-s1.wav \

我删除最后一个'\':

sed '$ s/.$//' script2 > script3

脚本3:

ep1-s1.wav \
ep2-s1.wav \
ep3-s1.wav

现在我想将该文件的内容用于sox,例如:

sox ep1-s1.wav \
ep2-s1.wav \
ep3-s1.wav output.wav

我怎样才能实现这个目标?

现在,可能有一种方法可以在一个命令中执行此操作,但我无法弄清楚管道是如何工作的:如果您知道如何操作,我真的很想知道!

答案1

就像我在评论中提到的,如果您不需要版本排序 ( sort -V),您可以简单地执行sox *wav.在 Linux 中,*wav将进行文件名扩展,产生按字母顺序排序的文件名列表。这受到您的区域设置的影响,尤其是LC_COLLATE,您可以通过 Google 获取更多信息。

如果您需要sort -V,处理此问题的正确方法是使用以 null 结尾的字符串和数组来处理带有空格和其他特殊字符的文件名。该脚本会将命令的输出放入sort一个数组中,并sox使用该列表运行。

#!/bin/bash

unset wav_files

while IFS= read -r -d '' file; do
   wav_files+=("$file")
done < <(find . -maxdepth 1 -type f -name "*wav" -print0 | sort -V -z)

if (( ${#wav_files[@]} == 0 )); then
   echo "No wav files found"
else
   sox -- "${wav_files[@]}"
fi

这可能超出您的预期,但这是一个很好的做法;)

答案2

当且仅当sort您的文件名“很好”,并且不包含空格或特殊字符(尤其是 glob 字符),简单的方法是在命令替换中运行:

sox $(printf "%s\n" *.wav | sort -V) output.wav

这里printf的作用是在每个文件名后面添加换行符 ( \n)。

(像往常一样,如果文件名有空格或制表符(在$(...)展开后它们将被分成两部分);或换行符(它们将在 之前被分成两部分sort);或全局字符(*?[],它们会扩展到任何匹配的文件名),所以如果您不知道文件名足够好,请不要这样做,请参见例如。https://mywiki.wooledge.org/WordSplitting什么时候需要双引号?

答案3

为什么不尝试一下:

sox `ls *.wax | sort -V`

相关内容