【问题标题】:how list just one file from a (bash) shell directory listing如何仅列出(bash)shell 目录列表中的一个文件
【发布时间】:2022-12-03 06:07:59
【问题描述】:

查询有点低,但这里是: bash 外壳脚本。 POSIX,薄荷 21

我只想要目录中的一个/任何 (mp3) 文件。作为样本。 在正常执行中,完整运行,代码将是这样的

for f in *.mp3 do
  #statements
done

这很好用,但是如果我想在不循环的情况下只对这样一个数组/glob(?)的一个文件进行采样,我该怎么做呢?我不在乎哪个文件,只是它是我正在工作的目录中的 mp3。 我应该只开始这个 for 循环,然后在一个语句后退出(中断),还是有更整洁的方式更适合工作的方式?

for f in *.mp3 do
  #statement
  break
done

Ta(不敢相信我问这个感觉有多蠢,看到答案我的额头会痛)

【问题讨论】:

  • 我会首先将所有文件名存储到一个数组中,然后从数组中随机选择一个元素,例如使用 bash 变量$RANDOM
  • arr=(*.mp3); f="${arr[0]}"?但它比你自己的解决方案好得多吗?注意:如果存在没有*.mp3文件的风险,请使用shopt -s nullglob
  • 带有 break 的 OP 代码似乎优于我。如果您不关心它们是什么,为什么要将火柴收集到内存中?
  • 我将研究那个“随机”的想法——虽然不需要随机——并且数组创建对于其他应用程序很方便(我正在学习东西),我不知道这样简单的“globbing”是可能的,甚至“对于 f与 python glob 相比,in *.mp3" 对我来说似乎不是特定的。但这就是我喜欢 shell 脚本的地方,就像我在命令行上一样。 @tripleee 你的评论帮助我看到什么是“更好”的平衡。感谢你们所有人
  • @Dee 因为你在问题中指定了 POSIX,所以我认为你需要知道 POSIX shell 没有“数组”

标签: bash shell file-handling


【解决方案1】:

我会在 POSIX shell 中这样做:

mp3file=
for f in *.mp3; do
    if [ -f "$f" ]; then
        mp3file=$f
        break
    fi
done
# At this point, the variable mp3file contains a filename which
# represents a regular file (or a symbolic link) with the .mp3
# extension, or empty string if there is no such a file.

【讨论】:

    【解决方案2】:

    由于您使用的是 Linux (Mint),因此您拥有 GNU find,因此从当前目录获取一个 .mp3 文件的一种方法是:

    mp3file=$(find . -maxdepth 1 -mindepth 1 -name '*.mp3' -printf '%f' -quit)
    
    • -maxdepth 1 -mindepth 1 导致搜索被限制在当前目录下的一级。
    • -printf '%f' 仅打印文件名(例如foo.mp3)。 -print 选项将打印文件名的路径(例如./foo.mp3)。这对你来说可能无关紧要。
    • -quit 导致 find 在找到并打印一个匹配项后立即退出。

    另一种选择是使用 Bash :(冒号)命令和$_(美元下划线)特殊变量:

    : *.mp3
    mp3file=$_
    
    • : *.mp3 以当前目录中的.mp3 文件列表作为参数运行: 命令。 : 命令忽略其参数并且不执行任何操作。
    • mp3file=$_mp3file 变量的值设置为提供给上一个命令 (:) 的最后一个参数。

    如果 .mp3 文件的数量很大(数百个或更多),则不应使用第二个选项,因为它会找到所有文件并在内部按名称对它们进行排序。

    在这两种情况下,应检查$mp3file以确保它确实存在(例如[[ -e $mp3file ]]),然后再将其用于其他任何事情,以防目录中没有.mp3文件。

    【讨论】:

      【解决方案3】:

      你使用的事实

      for f in *.mp3 do
      

      向我建议,MP3 的文件名中没有太多奇怪的字符。

      在那种情况下,如果您真的不关心哪个 MP3,您可以:

      f=$(ls *.mp3|head)
      statement
      

      或者,如果您每次都想要不同的:

      f=$(ls *.mp3|sort -R | tail -1)
      

      注意:如果你的文件名变得更复杂(包括空格或其他特殊字符),这将不再有效。

      【讨论】:

        【解决方案4】:

        假设您的文件名中没有空格,(我不明白为什么集体禁忌根本反对在脚本中使用 ls,而不是在文件名中没有空格,就个人而言)然后:-

        ls *.mp3 | tr ' ' '
        ' | sed -n '1p'
        

        【讨论】:

          猜你喜欢
          • 2012-05-21
          • 2019-06-03
          • 1970-01-01
          • 2013-07-08
          • 1970-01-01
          • 2011-06-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多