【问题标题】:How to pipe the output of `ls` to `mplayer`如何将`ls`的输出通过管道传输到`mplayer`
【发布时间】:2021-09-03 12:33:05
【问题描述】:

我想对文件夹中的所有文件运行mplayer按大小排序

我尝试了以下命令

ls -1S folder | mplayer
ls -1S folder | xargs mplayer
ls -1S folder | xargs -print0 mplayer

但这些都不起作用。

怎么做才对?

【问题讨论】:

  • 这能回答你的问题吗? Execute command on all files in a directory
  • 我尝试了“for i in ls -1S folder; do mplayer "$i"; done”,但由于文件名中的空格而出错
  • 你可以用空格循环文件;需要一些额外的脚本;参考这里:unix.stackexchange.com/q/9496
  • 我需要一个完整的脚本吗?在其他情况下,有一个可行的单行解决方案,例如find . -name "*.py" | xargs grep unittest
  • 你不应该在ls -lS中使用-l

标签: linux pipe


【解决方案1】:

Don’t parse the output of ls.

相反,使用例如for 循环文件并调用 stat 以获取文件大小。为避免文件名中出现空格或换行符问题,请使用以零结尾的字符串进行排序等:

for file in folder/*; do
    printf "%s %s\0" "$(stat -c %s "$file")" "$file"
done \
| sort -z -k1 -t ' ' \
| cut -z -f2- -d ' ' \
| xargs -0 mplayer

要为每个文件单独调用mplayer(而不是只调用一次,将所有文件作为参数传递),您需要使用while 循环,并在上面使用管道。不幸的是|不适用于while(至少我不知道如何),你需要使用process substitution来代替:

while IFS= read -r -d '' file; do
    mplayer "$file"
done < <(
    for file in folder/*; do
        printf "%s %s\0" "$(stat -c %s "$file")" "$file"
    done \
    | sort -z -k1 -t ' ' \
    | cut -z -f2- -d ' '
)

请注意,上面是 Bash 代码,并且使用 GNU 扩展,它可以在 Linux 上运行,但如果不进行更改就无法运行,例如在 macOS 上(BSD cut 没有 -z 标志,stat -c %s 需要更改为 stat -f %z)。

【讨论】:

  • op 希望文件按文件大小排序
  • @MarcoLucidi 谢谢,我没注意。我认为我的编辑现在应该解决 OP 的问题。
  • play.sh:第 3 行:意外标记附近的语法错误 &lt;' play.sh: line 3: done
  • @Alex 对不起,我应该说,这是 Bash 代码。看起来您正在 POSIX shell(破折号或类似)上运行?
  • 是的,你会认为使用文件列表是 shell 知道如何做得好的一件事,但事实并非如此。这真的很令人沮丧。 (代码可以使用fifos或临时文件而不是进程替换在POSIX Bourne Shell上工作,但这并不能真正降低复杂性)。
【解决方案2】:

我创建了一个 python 脚本来构建一个我想做的可执行文件。这是完整的python代码:

import os
import re
import sys
import glob

dir_name = sys.argv[1]

# Get a list of files (file paths) in the given directory 
list_of_files = filter( os.path.isfile,
                        glob.glob(dir_name + '/*') )

# Sort list of files in directory by size 
list_of_files = sorted( list_of_files,
                        key =  lambda x: os.stat(x).st_size)

# Iterate over sorted list of files in directory and 
# print them one by one along with size
for elem in list_of_files[::-1]:
    file_size  = os.stat(elem).st_size 
    print(f"mplayer {re.escape(elem)}")

您将输出重定向到文件并执行此操作。瞧——mplayer 按从大到小的顺序播放文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 2016-02-13
    • 1970-01-01
    • 2012-12-18
    • 2015-03-30
    • 1970-01-01
    相关资源
    最近更新 更多