【问题标题】:Why does my loop occasionally not read the entire line?为什么我的循环偶尔不会读取整行?
【发布时间】:2019-11-14 03:30:29
【问题描述】:

我已经用谷歌搜索这个问题几个小时了,以前从未遇到过。我有一个脚本,可以为我的公司 PRN 的教学视频创建缩略图 gif。当我运行它时,shell 有时会省略一半的文件路径,因此会失败。

这是在 debian 9 机器 (bash) 上。我尝试了很多方法来编写循环,包括管道到文件(结果正确),然后将其读回循环(然后混合我的输出)。我已经尝试从脚本的第一行设置 -x ,它似乎肯定是 shell 本身的问题。结果也各不相同。有时我输入一个文件并得到 30 个字符,有时它只读取 22 个字符,但失败的总是相同的文件。 od -xa 之间没有显示错误字符。

这是我当前的循环开始,也是事情开始失败的地方,所以我不会费心发布其余部分。

PPATH="/home/pi/pmount/prntest"

find "$PPATH" -type f -iname "*.mp4" >tempfile

cat -v tempfile | while read i
do
makethumbs "$i"
echo "$i" >>test.txt
done

例如文件的路径是/home/pi/pmount/prntest/Security Training/Example #1.mp4

示例输出:

/prntest/Security Training/Example #1.mp4

urity Training/Example #1.mp4`

当然无法解析。有任何想法吗?我将不胜感激。

编辑:

所需信息:

Shell: /bin/bash 

GNU bash, Version 4.4.12(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2016 Free Software Foundation, Inc. 

Linux 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u3 (2019-06-16) ``` 

【问题讨论】:

  • 你的拍子里有空格。尝试不使用 tmpfile,例如 find ...| while IFS= read -r ; do
  • 您好,感谢您的快速回答,但这不是解决方案。正如您在示例输出中看到的那样,它有时会在单词中间截断内容。许多带有空格的文件都运行良好。
  • 如果你做find "$PPATH" -type f -name '*.mp4' | while read i; do echo "$i"; done你有正确的值,我看不出有什么问题
  • 不知道是 makethumbs cmd 失败还是 echo "$i"。请将其归结为 echo "/home/pi/pmount/prntest/Security Training/Example #1.mp4" | makethumbs 或只是 echo "/home/pi/pmount/prntest/Security Training/Example #1.mp4" >> test.txt。您最近是否清理了test.txt 文件,您没有查看第一次交互错误输出,请检查文件底部,或> test.txt 将其归零。我认为您将不得不为您的示例记录发布od -xa 输出。 ....
  • 嗯.. 另外,请告诉我们echo $SHELLeval $SHELL --version。和uname -srv。好第一Q!你显然已经投入了研究!继续发帖,祝你好运。

标签: bash loops scripting filepath


【解决方案1】:

最好输出空的@9​​87654321@ 终止条目而不是换行符$'\n'find 命令的 -print0 选项正是这样做的。

这是您更正后的代码:

#!/usr/bin/env bash

PPATH=/home/pi/pmount/prntest

find "$PPATH" -type f -iname "*.mp4" -print0 >tempfile # write null-terminated strings to tempfile

while read -r -d '' i # -r do not expand globbing characters and -d '' use a null delimiter
do
  makethumbs "$i"
  echo "$i" >>test.txt
done <tempfile # inject the tempfile for the whole loop

【讨论】:

  • 谢谢你,但是这达到了相同的结果(虽然方法可能更好)。这里仍然没有运气。
【解决方案2】:

没有必要将 find 写入文件以立即读取它。还有,为什么要cat -v

我会这样做:

find "$PPATH" -type f -iname "*.mp4" -print -exec makethumbs {} ';' | tee test.txt

好的,makethumbs 是一个 shell 函数。仍然可以坚持这种方法:

export -f makethumbs 
find "$PPATH" -type f -iname "*.mp4" -print -exec bash -c '
    for file; do makethumbs "$file"; done
' _bash {} + | tee test.txt

使用 -exec cmd {} + 表单一次将多个文件传递给命令,以最大限度地减少生成的 bash shell 的数量。

需要将函数导出到环境中,以便子shell可以拾取它。

“_bash”参数是必需的,因为在使用-c 选项传递参数时,第一个参数被视为$0

【讨论】:

  • 感谢您的回答, cat -v 并且没有直接管道输出只是我尝试解决此问题的许多事情中的一部分。你的方法对我不起作用,因为 exec 找不到 shell 本地的函数。你的命令会让我重写脚本的主要部分。
  • 再次感谢您的编辑,但这对我不起作用,因为导出的函数无法访问全局变量。
猜你喜欢
  • 2019-05-26
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-20
  • 1970-01-01
相关资源
最近更新 更多