Shell常见错误有哪些总结?

2026-05-22 14:451阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计832个文字,预计阅读时间需要4分钟。

Shell常见错误有哪些总结?

原文:本文总结了编写Shell脚本中常见的错误。

本文归纳了Shell脚本编写中的常见错误总结。

本文总结了编写Shell脚本中的常见错误。

Blog:自由互联 个人
译自BashPitfalls

本文总结了编写Shell脚本中的常见错误。

for f in $(ls *.mp3)

最常犯的错之一就是编写这样的循环:

for f in $(ls *.mp3); do # Wrong! some command $f # Wrong! done for f in $(ls) # Wrong! for f in `ls` # Wrong! for f in $(find . -type f) # Wrong! for f in `find . -type f` # Wrong! files=($(find . -type f)) # Wrong! for f in ${files[@]} # Wrong!

确实,如果可以将ls的输出或者find作为文件名列表并对其进行迭代,看起来确实没啥问题。但是,这类方法是有缺陷的。

比如:

  • 如果文件名包含空格,for循环会将空格也分割(默认IFS为空格、\n\t),例如01 - Don't Eat the Yellow Snow.mp3for循环会分割成01-Don'tEattheYellowSnow.mp3
  • 如果文件名包含glob字符(例如*),包含它的单词将被识别为模式并用与其匹配的所有文件名列表替换。
  • 如果命令替换返回多个文件名,则无法区分第一个文件名的结束位置和第二个文件名的开始位置。路径名可以包含除NUL之外的任何字符。是的,这包括换行符。
  • ls实用程序可能会损坏文件名。根据您使用的平台、使用(或未使用)的参数以及其标准输出是否指向终端,ls可能会随机决定将文件名中的某些字符替换为“?”,或者干脆不打印它们。永远不要尝试解析ls的输出。ls完全是不必要的。它是一个外部命令,其输出专门供人读取,而不是由脚本解析。
  • 命令替代(Command Substitution)从其输出中剥离所有尾随换行符。这看起来可能是可取的,因为ls添加了一个换行符,但是如果列表中的最后一个文件名以换行符结束,则命令替代会删除换行符。

正确做法:

for file in ./*.mp3; do # Better! and… some command "$file" # …always double-quote expansions! done cp $file $target

如果 $file$target中有空格(如果没有修改$IFS),cp $file $target执行会报错,例如复制文件01 - Don't Eat the Yellow Snow.mp3/mn/usb

cp 01 - Don't Eat the Yellow Snow.mp3 /mnt/usb

会报以下错误:

cp: cannot stat ‘01’: No such file or directory cp: cannot stat ‘-’: No such file or directory cp: cannot stat ‘Don't’: No such file or directory cp: cannot stat ‘Eat’: No such file or directory cp: cannot stat ‘the’: No such file or directory cp: cannot stat ‘Yellow’: No such file or directory cp: cannot stat ‘Snow.mp3’: No such file or directory

正确做法:

Shell常见错误有哪些总结?

cp -- "$file" "$target"

本文共计832个文字,预计阅读时间需要4分钟。

Shell常见错误有哪些总结?

原文:本文总结了编写Shell脚本中常见的错误。

本文归纳了Shell脚本编写中的常见错误总结。

本文总结了编写Shell脚本中的常见错误。

Blog:自由互联 个人
译自BashPitfalls

本文总结了编写Shell脚本中的常见错误。

for f in $(ls *.mp3)

最常犯的错之一就是编写这样的循环:

for f in $(ls *.mp3); do # Wrong! some command $f # Wrong! done for f in $(ls) # Wrong! for f in `ls` # Wrong! for f in $(find . -type f) # Wrong! for f in `find . -type f` # Wrong! files=($(find . -type f)) # Wrong! for f in ${files[@]} # Wrong!

确实,如果可以将ls的输出或者find作为文件名列表并对其进行迭代,看起来确实没啥问题。但是,这类方法是有缺陷的。

比如:

  • 如果文件名包含空格,for循环会将空格也分割(默认IFS为空格、\n\t),例如01 - Don't Eat the Yellow Snow.mp3for循环会分割成01-Don'tEattheYellowSnow.mp3
  • 如果文件名包含glob字符(例如*),包含它的单词将被识别为模式并用与其匹配的所有文件名列表替换。
  • 如果命令替换返回多个文件名,则无法区分第一个文件名的结束位置和第二个文件名的开始位置。路径名可以包含除NUL之外的任何字符。是的,这包括换行符。
  • ls实用程序可能会损坏文件名。根据您使用的平台、使用(或未使用)的参数以及其标准输出是否指向终端,ls可能会随机决定将文件名中的某些字符替换为“?”,或者干脆不打印它们。永远不要尝试解析ls的输出。ls完全是不必要的。它是一个外部命令,其输出专门供人读取,而不是由脚本解析。
  • 命令替代(Command Substitution)从其输出中剥离所有尾随换行符。这看起来可能是可取的,因为ls添加了一个换行符,但是如果列表中的最后一个文件名以换行符结束,则命令替代会删除换行符。

正确做法:

for file in ./*.mp3; do # Better! and… some command "$file" # …always double-quote expansions! done cp $file $target

如果 $file$target中有空格(如果没有修改$IFS),cp $file $target执行会报错,例如复制文件01 - Don't Eat the Yellow Snow.mp3/mn/usb

cp 01 - Don't Eat the Yellow Snow.mp3 /mnt/usb

会报以下错误:

cp: cannot stat ‘01’: No such file or directory cp: cannot stat ‘-’: No such file or directory cp: cannot stat ‘Don't’: No such file or directory cp: cannot stat ‘Eat’: No such file or directory cp: cannot stat ‘the’: No such file or directory cp: cannot stat ‘Yellow’: No such file or directory cp: cannot stat ‘Snow.mp3’: No such file or directory

正确做法:

Shell常见错误有哪些总结?

cp -- "$file" "$target"