Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何在 Bash 中使用循环

如何在 Bash 中使用循环

作者头像
用户1880875
修改于 2021-09-18 09:52:26
修改于 2021-09-18 09:52:26
1.7K00
代码可运行
举报
运行总次数:0
代码可运行

人们希望学习批处理命令的一个普遍原因是要得到批处理强大的功能。如果你希望批量的对文件执行一些指令,构造一个可以重复运行在那些文件上的命令就是一种方法。在编程术语中,这被称作执行控制for 循环就是其中最常见的一种。

for 循环可以详细描述你希望计算机对你指定的每个数据对象(比如说文件)所进行的操作。

一般的循环

使用循环的一个简单例子是对一组文件进行分析。这个循环可能没什么用,但是这是一个安全的证明自己有能力独立处理文件夹里每一个文件的方法。首先,创建一个文件夹然后拷贝一些文件(例如 JPEG、PNG 等类似的文件)至文件夹中生成一个测试环境。你可以通过文件管理器或者终端来完成创建文件夹和拷贝文件的操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ mkdir example
$ cp ~/Pictures/vacation/*.{png,jpg} example

切换到你刚创建的那个新文件夹,然后列出文件并确认这个测试环境是你需要的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ cd example
$ ls -1
cat.jpg
design_maori.png
otago.jpg
waterfall.png

在循环中逐一遍历文件的语法是:首先声明一个变量(例如使用 f 代表文件),然后定义一个你希望用变量循环的数据集。在这种情况下,使用 * 通配符来遍历当前文件夹下的所有文件(通配符 * 匹配所有文件)。然后使用一个分号(;)来结束这个语句。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ for f in * ;

取决于你个人的喜好,你可以选择在这里按下回车键。在语法完成前,shell 是不会尝试执行这个循环的。

接下来,定义你想在每次循环中进行的操作。简单起见,使用 file 命令来得到 f 变量(使用 $ 告诉 shell 使用这个变量的值,无论这个变量现在存储着什么)所存储着的文件的各种信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
do file $f ;

使用另一个分号结束这一行,然后关闭这个循环:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
done

按下回车键启动 shell 对当前文件夹下所有东西的遍历。for 循环将会一个一个的将文件分配给变量 f 并且执行你的命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ for f in * ; do
> file $f ;
> done
cat.jpg: JPEG image data, EXIF standard 2.2
design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
otago.jpg: JPEG image data, EXIF standard 2.2
waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced

你也可以用这种形式书写命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ for f in *; do file $f; done
cat.jpg: JPEG image data, EXIF standard 2.2
design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
otago.jpg: JPEG image data, EXIF standard 2.2
waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced

对你的 shell 来说,多行和单行的格式没有什么区别,并且会输出完全一样的结果。

一个实用的例子

下面是一个循环在日常使用中的实用案例。假如你拥有一堆假期拍的照片想要发给你的朋友。但你的照片太大了,无法通过电子邮件发送,上传到图片分享服务也不方便。因此你想为你的照片创建小型的 web 版本,但是你不希望花费太多时间在一个一个的压缩图片体积上。

首先,在你的 Linux、BSD 或者 Mac 上使用包管理器安装 ImageMagick 命令。例如,在 Fedora 和 RHEL 上:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo dnf install ImageMagick

UbuntuDebian 上:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt install ImageMagick

在 BSD 上,使用 ports 或者 pkgsrc 安装。在 Mac 上,使用 Homebrew 或者 MacPorts 安装。

在你安装了 ImageMagick 之后,你就拥有一系列可以用来操作图片的新命令了。

为你将要创建的文件建立一个目标文件夹:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ mkdir tmp

使用下面的循环可以将每张图片减小至原来大小的 33%。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ for f in * ; do convert $f -scale 33% tmp/$f ; done

然后就可以在 tmp 文件夹中看到已经缩小了的照片了。

你可以在循环体中使用任意数量的命令,因此如果你需要对一批文件进行复杂的操作,可以将你的命令放在一个 for 循环的 dodone 语句之间。例如,假设你希望将所有处理过的图片拷贝至你的网站所托管的图片文件夹并且在本地系统移除这些文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ for f in * ; do
  convert $f -scale 33% tmp/$f
  scp -i seth_web tmp/$f seth@example.com:~/public_html
  trash tmp/$f ;
done

你的计算机会对 for 循环中处理的每一个文件自动的执行 3 条命令。这意味着假如你仅仅处理 10 张图片,也会省下输入 30 条指令和更多的时间。

限制你的循环

一个循环常常不需要处理所有文件。在示例文件夹中,你可能需要处理的只是 JPEG 文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ for f in *.jpg ; do convert $f -scale 33% tmp/$f ; done
$ ls -m tmp
cat.jpg, otago.jpg

或者,你希望重复特定次数的某个操作而不仅仅只处理文件。for 循环的变量的值是被你赋给它的(不管何种类型的)数据所决定的,所以你可以创建一个循环遍历数字而不只是文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ for n in {0..4}; do echo $n ; done
0
1
2
3
4

更多循环

现在你了解的知识已经足够用来创建自己的循环体了。直到你对循环非常熟悉之前,尽可能的在需要处理的文件的副本上进行操作。使用内置的保护措施可以预防损坏自己的数据和制造不可复现的错误,例如偶然将一个文件夹下的所有文件重命名为同一个名字,就可能会导致他们的相互覆盖。

更进一步的 for 循环话题,请继续阅读。

不是所有的 shell 都是 Bash

关键字 for 是内置在 Bash shell 中的。许多类似的 shell 会使用和 Bash 同样的关键字和语法,但是也有某些 shell ,比如 tcsh,使用不同的关键字,例如 foreach

tcsh 的语法与 Bash 类似,但是它更为严格。例如在下面的例子中,不要在你的终端的第 2、3 行键入 foreach? 。它只是提示你仍处在构建循环的过程中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ foreach f (*)
foreach? file $f
foreach? end
cat.jpg: JPEG image data, EXIF standard 2.2
design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
otago.jpg: JPEG image data, EXIF standard 2.2
waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced

在 tcsh 中,foreachend 都必须单独的在一行中出现。因此你不能像 Bash 或者其他类似的 shell 一样只使用一行命令创建一个 for 循环。

for 循环与 find 命令

理论上,你可能会用到不支持 for 循环的 shell,或者你只是更想使用其他命令的一些特性来完成和循环一样的工作。

使用 find 命令是另一个实现 for 循环功能的途径。这个命令提供了多种方法来定义循环中包含哪些文件的范围以及并行处理的选项。

find 命令顾名思义就是帮助你查询存储在硬盘里的文件。它的用法很简单:提供一个你希望它查询的位置的路径,接着 find 就会查询这个路径下面的所有文件和文件夹。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ find .
.
./cat.jpg
./design_maori.png
./otago.jpg
./waterfall.png

你可以通过添加名称的某些部分来过滤搜索结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ find . -name "*jpg"
./cat.jpg
./otago.jpg

find 命令非常好的地方在于你可以通过 -exec 参数标志将它查询到的每一个文件放入循环中。例如,只对存放在你的 example 文件夹下的 PNG 图片进行体积压缩操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ find . -name "*png" -exec convert {} -scale 33% tmp/{} \;
$ ls -m tmp
design_maori.png, waterfall.png

-exec 短语中,括号 {} 表示的是 find 正在处理的条目(换句话说,每一个被找到的以 PNG 结尾的文件)。-exec 短语必须使用分号结尾,但是 Bash 中常常也会使用分号。为了解决这个二义性问题,你的 结束符 可以使用反斜杠加上一个分号(\;),使得 find 命令可以知道这个结束符是用来标识自己结束使用的。

find 命令的操作非常棒,某些情况下它甚至可以表现得更棒。比如说,在一个新的进程中使用同一条命令查找 PNG 文件,你可能就会得到一些错误信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ find . -name "*png" -exec convert {} -flip -flop tmp/{} \;
convert: unable to open image `tmp/./tmp/design_maori.png':
No such file or directory @ error/blob.c/OpenBlob/2643.
...

看起来 find 不只是定位了当前文件夹(.)下的所有 PNG 文件,还包括已经处理并且存储到了 tmp 下的文件。在一些情况下,你可能希望 find 查询当前文件夹下再加上其子文件夹下的所有文件。find 命令是一个功能强大的递归工具,特别体现在处理一些文件结构复杂的情境下(比如用来放置存满了音乐人音乐专辑的文件夹),同时你也可以使用 -maxdepth 选项来限制最大的递归深度。

只在当前文件夹下查找 PNG 文件(不包括子文件夹):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ find . -maxdepth 1 -name "*png"

上一条命令的最大深度再加 1 就可以查找和处理当前文件夹及下一级子文件夹下面的文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ find . -maxdepth 2 -name "*png"

find 命令默认是查找每一级文件夹。

循环的乐趣与收益

你使用的循环越多,你就可以越多的省下时间和力气,并且可以应对庞大的任务。虽然你只是一个用户,但是通过使用循环,可以使你的计算机完成困难的任务。

你可以并且应该就像使用其他的命令一样使用循环。在你需要重复处理单个或多个文件时,尽可能的使用这个命令。无论如何,这也算是一项需要被严肃对待的编程活动,因此如果你需要在一些文件上完成复杂的任务,你应该多花点时间在规划自己的工作流上面。如果你可以在一份文件上完成你的工作,接下来将操作包装进 for 循环里就相对简单了,这里面唯一的“编程”的需要只是理解变量是如何工作的并且进行充分的规划工作将已处理过的文件和未处理过的文件分开。经过一段时间的练习,你就可以从一名 Linux 用户升级成一位知道如何使用循环的 Linux 用户,所以开始让计算机为你工作吧!

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
开发者应该了解的 10 个 Linux 命令
作为一名软件工程师,我做过的最明智的投资就是学习 Linux。因为,在日常工作中,我们会经常与 Linux 系统打交道。而今天,作为一名 30 多岁的工程师,我仍受益于几年前我碰巧学过的那些知识,所以技术学习需要不断积累,不积跬步无以至千里。
开发者技术前线
2020/11/23
7150
开发者应该了解的 10 个 Linux 命令
CVE-2016-3714 - ImageMagick 命令执行分析
ImageMagick是一款使用量很广的图片处理程序,很多厂商都调用了这个程序进行图片处理,包括图片的伸缩、切割、水印、格式转换等等。但近来有研究者发现,当用户传入一个包含『畸形内容』的图片的时候,就有可能触发命令注入漏洞。
phith0n
2020/10/15
1.1K0
Shell 命令行,写一个自动整理 ~/Downloads/ 文件夹下文件的脚本
本文讲述了一位技术编辑人员通过编写脚本自动整理下载文件夹的脚本,以便使文件更加有序和易于管理。该脚本使用 find 命令和 mv 命令将文件移动到目标文件夹,并修改文件名。此脚本适用于 CentOS 和 macOS 系统,并已在测试中成功运行。
FungLeo
2018/01/08
2.1K0
Shell 命令行批量处理图片文件名
本文介绍了如何用shell批量处理图片文件名,包括循环所有文件、重命名以及根据MD5值命名。首先,通过循环所有文件,将文件移动到一个新的文件夹中,并计算每个文件的MD5值。然后,根据MD5值重命名文件,并将其移动到相应的文件夹中。该方案适用于MAC系统,在Linux系统中可能需要细微调整。
FungLeo
2018/01/08
2K0
JPEG/Exif/TIFF格式解读(2):图片元数据保存及EXIF详解
元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息。用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。
周陆军博客
2023/04/22
10.7K0
ImageMagick 的安装及使用
ImageMagick是一款免费开源的图片编辑软件。既可以通过命令行使用,也可以通过C/C++、Perl、Java、PHP、Python或Ruby调用库编程来完成。ImageMagic的主要精力集中在性能,减少bug以及提供稳定的API和ABI上。
全栈程序员站长
2022/09/07
2.9K0
ImageMagick 的安装及使用
h5ai服务器目录
在前几天,我帮人安装h5ai这个东西,结果直接踩坑,装了一个下午,打算自己也装一个,顺便写一下教程 最终效果演示:
huanhao
2020/04/11
1.2K0
h5ai服务器目录
python︱批量操作文件(os)、图片操作技巧(下载网络图片、skimage.io)
该文章介绍了如何计算两个矩形框的重叠面积以及交并比,并提供了具体的Python代码示例。同时,文章还介绍了如何利用PIL库中的ImageDraw模块来绘制矩形框和文字。此外,文章还介绍了如何将计算得到的交并比结果可视化,并给出了一个示例代码。
悟乙己
2018/01/02
8.2K0
python︱批量操作文件(os)、图片操作技巧(下载网络图片、skimage.io)
快速搭建一个下载站:详解Linux上部署h5ai实现目录映射
H5AI,其实全称是:HTML5 Apache Index。最初是用来在Apache Web服务器上,完成资源映射,但是后来适配到Nginx等其他平台。使用H5AI的效果:
Mintimate
2021/08/04
6.6K0
快速搭建一个下载站:详解Linux上部署h5ai实现目录映射
ImageMagick
我对ImageMagick的主要功能做一个简单的介绍,其中覆盖的大都是人们常用的一些功能,如果你要全面的了解它的知识,你可以看看它的man手册。
云深无际
2021/04/14
1.1K0
ImageMagick
imagemagick邂逅getimagesize的那点事儿
前段时间写的文章,在微博上说HW结束分享一下,总算可以发了。感谢 @voidfyoo 提出的这个问题。
phith0n
2023/10/28
3240
imagemagick邂逅getimagesize的那点事儿
Hybris商品图片导入与压缩有关的配置
1.   在电脑上安装 ImageMagick 软件(windows平台还需要安装VC++),下载路径:http://www.imagemagick.org/script/download.php#w
JMCui
2018/03/16
1.1K0
Hybris商品图片导入与压缩有关的配置
文件上传靶机实验记录
前端JS后缀名校验,通过审查元素发现onsubmit="return checkFile()”校验函数我们将其删除直接上传(浏览器禁用JS脚本也能上传,BURP抓包更改后缀名也能上传)webshell。
菜菜有点菜
2022/03/18
6K0
文件上传靶机实验记录
Python自动化办公-玩转图片
有很多非 IT 行业的朋友都在学 Python,他们的目的也很简单,就是想提高下工作效率,简单重复的工作希望用 Python 搞定。
somenzz
2021/07/23
6500
Upload-labs(1-15)详解
想到这也就知道是绕过方法中的黑名单绕过了,上面的不让上传,想到了可以上传.php5的文件,除了这个还有.phtml.phps .pht 但是要想上传后能执行,要在自己的apache的httpd.conf文件写入
ly0n
2020/11/04
7.5K0
Upload-labs(1-15)详解
从Slideshare.net 下载Slide的方法:
    Slideshare.net上有很多不错的Slide都没有提供下载链接,平常倒也无所谓,都是收藏后直接在线观看的。
Enjoy233
2019/03/05
12.1K0
图片之EXIF信息提取与处理利用
Exif(Exchangeable image file format 可交换图像文件格式),是一种图像文件格式,其数据存储与JPEG格式是完全相同的,EXIF可以附加于JPEG、TIFF、RIFF、RAW等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。
全栈工程师修炼指南
2022/09/28
4.6K0
图片之EXIF信息提取与处理利用
Upload-labs&Upload Bypass Summarize
暑假闲着也是闲着,去年这个时候刷完了 sqli-labs,今年想着来刷一下 upload-labs 而这次重点不在于题解,而在于总结与归纳 首先我们得明确一点,即上传的过程
安恒网络空间安全讲武堂
2018/12/26
1.5K1
常用简单命令_bash笔记2
感谢支持ayqy个人订阅号,每周义务推送1篇(only unique one)原创精品博文,话题包括但不限于前端、Node、Android、数学(WebGL)、语文(课外书读后感)、英语(文档翻译) 如果觉得弱水三千,一瓢太少,可以去 http://blog.ayqy.net 看个痛快
ayqy贾杰
2023/03/15
5900
常用简单命令_bash笔记2
Python将PDF转成图片—PyMuPDF和pdf2image
前言:在最近的测试中遇到一个与PDF相关的测试需求,其中有一个过程是将PDF转换成图片,然后对图片进行测试。
软测小生
2019/08/06
2.9K0
Python将PDF转成图片—PyMuPDF和pdf2image
相关推荐
开发者应该了解的 10 个 Linux 命令
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验