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.mp3,
for循环会分割成
01、
-、
Don't、
Eat、
the、
Yellow、
Snow.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
正确做法:
cp -- "$file" "$target"
强烈建议:引用变量的时候,一定要加双引号。
Filenames with leading dashes
如果文件名带有-
,命令可能错误把它当作参数。
解决的方法之一是,在变量前面加--
,例如:
cp -- "$file" "$target"
加--
是告诉命令,停止扫描参数。
注意:此方法的潜在问题,必须确保每条命令都要插入
--
,这很容易遗漏。
还有一种方法是使用相对路径或者绝对路径。例如:
for i in ./*.mp3; do
cp "$i" /target
…
done
在这种情况下,即使开头包含-
的文件,也可以确保变量始终包含类似./-foo.mp3
的文件,这样就比较安全。
[ $foo = "bar" ]
如果[
中引用的变量不存在或为空,则[
命令最终将如下所示:
[ = "bar" ] # Wrong!
Tips:
=
是二元一次运算符,不是一元一次运算符。
如果变量包含内部空格,则会在[
命令看到它之前将其拆分成单独的单词,例如:
[ multiple words here = "bar" ]
看起来没啥问题,但在[]
语法中是错误的,正确方式是加上双引号:
# POSIX
[ "$foo" = bar ] # Right!
# Bash / Ksh
[[ $foo == bar ]] # Right!
cd $(dirname "$f")
这也是引用错误。正确做法:
cd -P -- "$(dirname -- "$f")"
Tips:
-p
参数是递归处理,将指定目录下的所有文件与子目录一并处理。
Shell:常见错误总结(一)的更多相关文章
- (转)Hadoop之常见错误集锦
Hadoop之常见错误集锦 下文中没有特殊说明,环境都是CentOS下Hadoop 2.2.0.1.伪分布模式下执行start-dfs.sh脚本启动HDFS时出现如下错误: ...
- Shell常见用法小记
shell的简单使用 最近发现shell脚本在平常工作中简直算一把瑞士军刀,很多场景下用shell脚本能实现常用的简单需求,而之前都没怎么学习过shell,就趁机把shell相关的语法和常见用法总结了 ...
- Elasticsearch 集群和索引健康状态及常见错误说明
之前在IDC机房线上环境部署了一套ELK日志集中分析系统, 这里简单总结下ELK中Elasticsearch健康状态相关问题, Elasticsearch的索引状态和集群状态传达着不同的意思. 一. ...
- centos linux 系统日常管理4 scp,rsync,md5sum,sha1sum,strace ,find Rsync 常见错误及解决方法 第十七节课
centos linux 系统日常管理4 scp,rsync,md5sum,sha1sum,strace ,find Rsync 常见错误及解决方法 第十七节课 rsync可以增量同步,scp不行 ...
- hadoop常见错误总结三
问题导读:1.... could only be replicated to 0 nodes, instead of 1 ...可能的原因是什么?2.Error: java.lang.NullPoin ...
- 解决hadoop 集群启动常见错误办法
hadoop 集群常见错误解决办法 hadoop 集群常见错误解决办法: (一)启动Hadoop集群时易出现的错误: 1. 错误现象:Java.NET.NoRouteToHostException ...
- hadoop 集群常见错误解决办法
hadoop 集群常见错误解决办法 hadoop 集群常见错误解决办法: (一)启动Hadoop集群时易出现的错误: 1. 错误现象:Java.NET.NoRouteToHostException ...
- Git学习之常见错误 clone被拒绝
Git学习之常见错误 问题: git clone 时 报错 Permission Denied (权限被拒绝). 解决方法: 需要把本地的公钥上传到服务器. 解决步骤: ①第一步,设置本地的git的用 ...
- 笔记:npm常见错误
常见错误 破坏的npm安装 随机错误 找不到兼容版本 权限错误 Error: ENOENT, stat 'C:\Users\<user>\AppData\Roaming\npm' 在Win ...
随机推荐
- like使用索引如何避免失效
1 准备数据 1.1 建表 DROP TABLE IF EXISTS staff; CREATE TABLE IF NOT EXISTS staff ( id INT PRIMARY KEY auto ...
- Solution -「多校联训」小卖部
\(\mathcal{Description}\) Link. 有 \(n\) 种物品,第 \(i\) 中有 \(a_i\) 个,单价为 \(b_i\).共 \(q\) 次询问,每次查询用不超 ...
- STM32 HAL 库实现乒乓缓存加空闲中断的串口 DMA 收发机制,轻松跑上 2M 波特率
前言 直接储存器访问(Direct Memory Access,DMA),允许一些设备独立地访问数据,而不需要经过 CPU 介入处理.因此在访问大量数据时,使用 DMA 可以节约可观的 CPU 处理时 ...
- Linux-CPU优化之平均负载率
一.平均负载率定义 平均负载是指单位时间内,系统处于可运行状态 和不可中断状态 的平均进程数,也就是平均活跃进程数,它和CPU 使用率并没有直接关系. 可运行状态的进程:是指正在使用 CPU 或者正在 ...
- CPU、进程、线程原理
巨人的肩膀 看完这篇还不懂高并发中的线程与线程池你来打我 (qq.com)
- OC之判断数组最大最小值
超简单的筛选方法 array为你筛选的数组 NSNumber * max = [Array valueForKeyPath:@"@max.floatValue"]; NSNumbe ...
- java运行原理、静态代理和动态代理区分
1.java的编译和运行原理: ■ 编译:将源文件 .java 文件,通过编译器(javac 命令) 编译成 字节码文件 .class 文件. ■ 运行,通过类加载器(以二进制流形式)把字节码加载进J ...
- Wireshark教程之过滤器设置
实验目的 1.工具介绍 2.主要应用 实验原理 1.网络管理员用来解决网络问题 2.网络安全工程师用来检测安全隐患 3.开发人员用来测试执行情况 4.学习网络协议 实验内容 1.抓取特定数据流 2.显 ...
- [题解]第十一届北航程序设计竞赛预赛——I.神奇宝贝大师
题目描述 一张n*m的地图,每个格子里面有一定数量的神奇宝贝,求一个最优位置,使得所有神奇宝贝到该位置的曼哈顿距离最小. 一共有T组数据,每组数据包含两行,第一行是n和m(1<=n,m<= ...
- 号外!号外!这个敏捷高效的大数据bi看板可以免费使用啦!
随着信息革命的深入推进,数据已经成为国家基础性战略资源,各个行业开始重视数据分析,企业不同,数据分析需求当然不一样,如销售行业需要对商品进行销售分析:网站运营需要进行用户.渠道.流量等信息分析:制造行 ...