使用 awk 命令输出 ls 命令

使用 awk 命令输出 ls 命令

我有一个具有以下格式的电子书目录:

<authorname> <authorsurname> - <bookname>

我想按作者分类书籍。我在 for 循环中使用以下命令进行此操作:

for author in $(ls /home/me/books | awk -F "-" '{print $1}' | sort | uniq)
do
    make a directory and push all books of this author to this directory 
done

我希望看到作者姓氏下一个的值作者姓名值,但这些值会逐行打印。如果我在 for 循环中单独运行 ls 命令,那么它会按我想要的方式运行(输出 1)。但在循环中,它不会运行(输出 2)。

视觉输出:

我想要的是:

Edgar Allan Poe
Marcus Aurelius

会发生什么:

Edgar
Allan
Poe
Marcus
Aurelius

我该如何解决这个问题,并将作者按姓名和姓氏排在同一行?

编辑:我尝试“cat”一个包含作者姓名的文件。但它也没有用。

答案1

的扩展值$(command)是一个单一的扁平字符串,包含命令输出的所有行。它不是由多行组成的数组。

所有不带引号的 shell 扩展,无论是$variables还是$(commands),都受单词拆分。顾名思义,默认情况下,该值被拆分为单个单词 -不是线条– 根据在 $IFS 中找到的分隔符。

要循环遍历每一行,可以使用mapfile将输入导入到实际的数组变量(每行作为一个单独的数组元素,稍后可以看到declare -p authors)...

mapfile -t authors < <(ls | awk)

for author in "${authors[@]}"; do
    ...
done

# Note that the < and the <() are two independent operators.
# < <() is used instead of ls|awk|mapfile because pipeline elements
# run in their own scope and cannot alter "parent" variables.

...或者for用管道和“读取”循环替换...

ls | awk | while read -r author; do
    ...
done

# In this case, using a pipeline is okay as long as the 'while' loop
# doesn't need to make variable modifications that remain after the loop.

...或者完全跳过整个过程并只使用通配符扩展:

for book in /home/me/books/*; do
    filename=${book##*/}
    author=${filename%% - *}
    make a $author directory if needed, then move this one book to that directory
done

# Expansions within the right-hand side of a variable assignment
# are actually exempt from word splitting, so they can remain unquoted.

相关内容