【问题标题】:sed can't read executable files when iterating in for loopsed 在 for 循环中迭代时无法读取可执行文件
【发布时间】:2020-08-02 21:25:22
【问题描述】:

在终端 shell 中,我试图遍历一组 Python 文件并使用 sed 执行查找和替换,例如:

$ for f in `ls *.py`; do sed -i 's|foo|bar|g' $f; done;

但是,对于某些文件(尤其是那些我已更改为可执行的 Python 脚本),它会给出错误:

sed: can't read example_script.py: No such file or directory

为什么它可能不适用于可执行文件,但适用于其他文件?

【问题讨论】:

  • Why not parse ls?。使用for f in *.py; do
  • 为什么在这种情况下使用ls

标签: bash sed ls


【解决方案1】:

sed 没有读取可执行文件的原因是因为我将ls 别名为ls --color=auto。因此,ls在for循环中返回的文件名不仅仅是带有文件名的ascii字符串,它们还包含颜色信息,例如:

''$'\033''[01;32mexample_script.py'$'\033''[0m'

所以 sed 找不到这个奇怪的文件!

正如 cmets 中所指出的,在这种情况下,实际上不需要使用 ls 来创建我的可迭代列表,而是可以这样做:

$ for f in *.py; do sed -i 's|foo|bar|g' "$f"; done;

甚至没有 for 循环:

$ sed -i 's|foo|bar|g' *.py

原始答案:这是我对后代的原始答案,保留在这里是因为这是我自己在评论者的帮助之前所做的。

我的解决方案(假设已设置此别名)是改为运行我的 for 循环,确保指定 ls --color=none,即:

$ for f in `ls --color=none *.py`; do sed -i 's|foo|bar|g' $f; done;

【讨论】:

  • 正确的解决方案是根本不使用ls。您可以直接在for 语句中使用文件通配符:for f in *.py ; do
  • 我认为问题的前提是有缺陷的(为什么这种反模式不能正常工作?)但唯一正确的答案是使用 glob,所以我会删除你的中间部分回答,因为它的损坏程度仅比原始尝试少一点(尝试使用example script.py,这是一个完全有效的文件名)。
  • 使用"$f" 来避免因文件名引起的问题...我宁愿使用sed -i 's|foo|bar|g' *.py 并完全避免循环
  • 另外,别名问题只出现在交互会话中;在非交互式会话中(例如运行脚本时),别名默认关闭。
  • 不,它不是别名扩展。这只发生在交互式 shell 中,而不是脚本中(除非您明确打开它,但没有人这样做)。你的错误信息是一致的,比如存在带空格的文件,比如my example_script.py
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
  • 2020-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多