1. mkdir -p
:递归创建文件夹
- 应用举例:
image.png
参考: https://stackoverflow.com/questions/793858/how-to-mkdir-only-if-a-dir-does-not-already-exist
注意:逗号之间务必不要加空格。(shell脚本中一般都不允许额外的空格)
- 更新: mkdir -p 还包含了对文件路径的检查,同下面代码,但是显然更加elegant:
if [ ! -d dirName ]; then
mkdir dirName;
fi
2. sort --random-sort
: 随机选取元素
- 应用举例:
ls target_dir | sort --random-sort | head -n 100 | xargs -i cp -v target_dir/{} .
在某个文件夹中随机抽取100个文件,并拷贝到当前文件夹
3. list files without specific pattern 列出文件时排除某些模式
动机:
实现该功能的动机是在ls或者copy时想要排除掉文件夹。在网上找了下,有两个比较好的方案:
3.1. ls -I"xx"
或ls --ignore="xxx"
这是最直接的方法,可以去除某种特定pattern。优点是简洁易用,缺点是无法直接排除所有dir,只能通过dir名字进行排除。
-
应用举例:
image.png
注意,这里-I
和--ignore
是一回事,前面是简写而已(类比argparse)。
3.2. find . -maxdepth 1 -type -f -not -name 't_*'
这个命令非常好用,有必要详细记录下。可以同时exclude文件夹以及不想要的pattern,还可以选择recursive的深度。
-
-maxdepth
指定递归深度。设为1则只返回当前路径的结果(不包含子文件夹内的文件) -
-type f
只返回files,不返回directories或者其他的device nodes等等 -
-not -name
组合使用,可以排除掉某些不想要的名字
4. #!/bin/bash
: zsh下执行shell脚本的一个坑
之前在bash下写shell脚本,一直觉得#!/bin/bash
没啥用,就经常不写,有时候写的话还老写不完整。最近在虚拟机用zsh执行一个shell脚本,显示不支持其中if语句后面的"[["。为了解决这个问题搜索了很久,以为是bash的环境变量没添加到zshrc中。后来还发现zsh原来有自己的一套shell语句规范,和bash稍有不同。但是这都不是我要的答案。
最后终于找到问题所在,其实zsh不存在不兼容bash脚本的问题,只需要在脚本头部添加一句#!/bin/bash
,要求使用bash执行当前脚本就行了。我当时写错了写成#/bin/bash
,结果一直报错....
参考: https://unix.stackexchange.com/questions/15950/how-to-list-files-without-directories-and-filter-by-name-ls-options
5. 关于前缀和后缀(文件名或者command line output)
- 5.1 批量修改文件名(加前缀或者后缀)
awk '$0="prefix"$0' file > new_file
简单而强大。有时间要把awk好好学一学。
- 5.2 终端命令行
场景:假如我有两个文件夹,一个叫flowers,存放许多花的照片,包含不同品种;另一个叫masks,存放每图片对应的前景mask。现在我进入放置花的文件夹中随便挑了若干张我喜欢的,然后把它们拷贝到其他文件夹。现在我想把masks中对应的图片也挑出来,放到一起(显然对应的flower图片和mask图片之间有部分相同的pattern)。我想用一句shell命令完成这个操作。
(注:某一对图片的名称分别为:image_xxx_0001.png 和 mask_xxx_0001.png,xxx为类别名称)
ls | grep png | cut -d _ -f 2,3 | sed 's/.*/mask_&/' | xargs -i cp masks/{} .
第一部分很简单,通过grep筛选出png文件,用cut -d -f找到mask和flower文件夹中相同的pattern;第二部分批量加前缀 “mask_”。即找到了masks文件夹中对应的文件。
此外, 可以用cut -d _ -f 2-
返回后面的所有字符。
-
sed
的灵活用法:
ls | grep txt | sed 's/.*/prefix&suffix/'
6. 强大的awk
6.1 简介:
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。 awk的创建者将其定义为“样式扫描和处理语言”,允许我们创建简短的程序,读取输入文件、为数据排序、处理数据、对输入文件执行计算以及生成报表等。
6.2 使用方法:
awk '{pattern + action}' {filename}
注意,花括号不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。pattern就是要表示的正则表达式,用斜杠括起来。
-
awk最基本的功能是在文件或字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。
-
awk通常以文件的一行作为处理单位。
6.3 实例学习
6.4 实用的场景举例
-
将一个csv文件的所有浮点数转换为整数(该文件中既包含整数形式也有部分浮点数形式)
bounding box csv文件.png
-
awk 'BEGIN {FS=" +|,";} {printf("%s','%.0f %.0f %.0f %.0f\n", $1,$2,$3,$4,$5);}' train_labels.csv
注意printf中要格式化输出空格,直接用空格即可。不需要用\0之类的
- 用于获取某个路径下所有标注文件(xml)中包含了哪几种类别
ls $1 | awk -v var=$1 '/xml/{print "cat "var"/"$0" | grep /name"}' | bash | awk -F '>|<' '{print $3}' | uniq | tr "\n" " " > $1/ClassNames.txt
解释:
①$1为包含标注图像数据的路径
②在awk语句中使用shell变量:参考:
https://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-script
③一个典型的VOC类型的物体检测标注xml文件:
grep /name
提取出包含标记类别的行④第二个awk用于从
<name>hand</name>
中提出hand。感觉应该有更简练的提取方法。⑤
tr "\n" " "
用于将行形式的输出转换为列形式
7. 拷贝目录
- 场景:有时候在远程服务器上工作时,想要拷贝或者是远程拷贝一个目录给同事,但是可能同事比较在意这个目录结构以及脚本(不要小看了“结构”,很多组织有序的文件夹就是一个Python module~),但是不在意目录里面的数据集(可能有多个位置存放数据,且占空间较大)。也就是说,我希望拷贝整个目录结构,同时exclude掉不想要的pattern,如
*.jpg
,或者一些较大的模型权重,如.h5
,但是又保留他们各自所在的子文件夹,以便让我的同事知道这个文件夹应该放数据集,那个文件夹应该放权重。如何快速做到这些?
- 先考虑一个稍微简单但是常用点的,获取某个路径所有文件夹名字并在目标路径中创建这些文件夹。如果是以前,我应该会这么做(复习下数组):
dirList=(`find . -maxdepth 1 -type d -not -name "." | awk -F '/' '{print $2}' | tr "\n" " "`)
for item in ${dirList[@]};do mkdir $TARGET/$item;done
- 解决:只需要一句命令:
rsync
参考:https://stackoverflow.com/questions/4585929/how-to-use-cp-command-to-exclude-a-specific-directory/14789400#14789400?newreg=ebc0a9fd681045a3b061bc7aecf5cd07 -
举例:
原目录结构
为了给同事一个干净的文件夹,我不想拷贝以下内容:1.jpg文件,2. .h5文件,3. pycahce文件夹 4. 一些错误文件类似events.out.tfevents.1548346771.fpc
- 现在看看我的这行命令:
rsync -av --progress toolkit_yolo_map tst_destination
--exclude="*.jpg" --exclude="*.xml" --exclude="*.h5"
--exclude="__pycache__" --exclude="result/*" --exclude="*events*"
看起来是不是很长?再仔细看下,有效的就三个部分,原目录,目标目录,多个exclude模式,极其简单。再看看效果:
$ tree tst_destination
tst_destination
└── toolkit_yolo_map
├── 2007_train.txt
├── 2007_val.txt
├── before_training.sh
├── boom.sh
├── data
│ ├── augDataset
│ │ ├── aug_labels.csv
│ │ ├── clean
│ │ └── display
│ ├── create_aug_dataset.sh
│ ├── DataAugmentation.py
│ ├── legacy
│ │ ├── arange_auged_label.sh
│ │ └── train_labels.csv
│ ├── test_dataset
│ ├── train_dataset
│ ├── train_labels.csv
│ └── train_xml
├── finetune_baseline_on_aug_dataset.py
├── font
│ ├── FiraMono-Medium.otf
│ └── SIL Open Font License.txt
├── kmeans.py
├── logs
│ └── confidente_model
│ ├── finetune.log
│ ├── loss_curve.png
│ └── train_val_loss.csv
├── model_data
│ ├── coco_classes.txt
│ ├── my_classes.txt
│ ├── new_yolo_anchors.txt
│ ├── tiny_yolo_anchors.txt
│ ├── voc_classes.txt
│ └── yolo_anchors.txt
├── plot_training_curve.py
├── README.md
├── result
├── src
│ ├── dataConfig.sh
│ ├── kmeans.py
│ ├── step_1_process_data.py
│ ├── step_2_mv_data.py
│ ├── step_3_voc_annotation.py
│ ├── step_4_train.py
│ ├── step_5_yolo_video.py
│ └── yolo.py
├── tmp_data
│ ├── augDataset
│ │ ├── aug_labels.csv
│ │ ├── clean
│ │ └── display
│ ├── create_aug_dataset.sh
│ ├── legacy
│ │ ├── arange_auged_label.sh
│ │ └── train_labels.csv
│ ├── test_dataset
│ ├── train_dataset
│ ├── train_labels.csv
│ └── train_xml
├── train_finetune.sh
├── VOCdevkit
│ └── VOC2007
│ ├── Annotations
│ ├── ImageSets
│ │ └── Main
│ │ ├── test.txt
│ │ ├── train.txt
│ │ └── val.txt
│ └── JPEGImages
├── yolo3
│ ├── __init__.py
│ ├── model.py
│ └── utils.py
└── yolo_anchors.txt
- 结束。上面的Stack Overflow中有很多其他有趣的答案,非常值得一看。
8. 记mac下终端命令行下的一个小坑(对比linux命令行)
- 环境: ubuntu和mac下均为zsh命令行
- 今天在mac和ubuntu上执行同一个脚本时发现出现了不一样的结果,仔细追究了一下,原来是mac和linux上的grep命令有一个小小的差异。首先给出一段我正在预处理的文本:
[Chiyuan info] VehicleInfo: throttle: 27.756, brake: 14.633
Serializer frame count: 0
[Chiyuan info] Current Position: ( 395855.807, 3416411.559, 16.373 )
[Chiyuan info] Current Heading: -0.590
[Chiyuan info] VehicleInfo: throttle: 27.756, brake: 14.644
Serializer frame count: 0
[Chiyuan info] Current Position: ( 395855.807, 3416411.559, 16.373 )
[Chiyuan info] Current Heading: -0.590
[Chiyuan info] VehicleInfo: throttle: 27.768, brake: 14.644
Serializer frame count: 0
[Chiyuan info] Current Position: ( 395855.807, 3416411.559, 16.373 )
[Chiyuan info] Current Heading: -0.590
[Chiyuan info] VehicleInfo: throttle: 27.768, brake: 14.627
^[[0;31mE0710 14:32:40.377712 2032 localization_util.cpp:337] [ERROR] [GetCarPoseFromWindow] input timestamp behind of pose window end[input time, window end] : 11976256, 1562740358270000128
^[[m^[[0;31mE0710 14:32:40.378336 2032 localization_querier.cpp:286] [ERROR] [LOCALIZATION] car pose unusable please check from_timestamp_ns
^[[mlidarfreespace carpose error: 11976256
[Chiyuan info] Current Position: ( 395855.807, 3416411.559, 16.373 )
[Chiyuan info] Current Heading: -0.590
[Chiyuan info] VehicleInfo: throttle: 27.756, brake: 14.627
[Chiyuan info] Current Position: ( 395855.909, 3416411.493, 16.374 )
[Chiyuan info] Current Heading: -0.587
[Chiyuan info] VehicleInfo: throttle: 27.756, brake: 14.624
[Chiyuan info] Current Position: ( 395855.935, 3416411.477, 16.374 )
[Chiyuan info] Current Heading: -0.586
[Chiyuan info] VehicleInfo: throttle: 27.756, brake: 14.624
Serializer frame count: 1
[Chiyuan info] Current Position: ( 395855.935, 3416411.477, 16.374 )
[Chiyuan info] Current Heading: -0.586
[Chiyuan info] VehicleInfo: throttle: 27.756, brake: 14.604
Serializer frame count: 1
Serializer frame count: 1
[Chiyuan info] Current Position: ( 395855.935, 3416411.477, 16.374 )
[Chiyuan info] Current Heading: -0.586
[Chiyuan info] VehicleInfo: throttle: 27.659, brake: 14.604
^[[0;31mE0710 14:32:40.430655 2032 localization_util.cpp:337] [ERROR] [GetCarPoseFromWindow] input timestamp behind of pose window end[input time, window end] : 11976256, 1562740358350000128
^[[m^[[0;31mE0710 14:32:40.431396 2032 localization_querier.cpp:286] [ERROR] [LOCALIZATION] car pose unusable please check from_timestamp_ns
^[[mlidarfreespace carpose error: 11976256
[Chiyuan info] Current Position: ( 395855.935, 3416411.477, 16.374 )
[Chiyuan info] Current Heading: -0.586
[Chiyuan info] VehicleInfo: throttle: 27.659, brake: 14.604
[Chiyuan info] Current Position: ( 395855.935, 3416411.477, 16.374 )
[Chiyuan info] Current Heading: -0.586
[Chiyuan info] VehicleInfo: throttle: 27.475, brake: 14.604
[Chiyuan info] Current Position: ( 395855.961, 3416411.460, 16.374 )
[Chiyuan info] Current Heading: -0.585
[Chiyuan info] VehicleInfo: throttle: 27.475, brake: 14.583
然后对这个log文件进行同样的处理:cat test.log | grep -A3 frame
:
ubuntu上给出的结果:
Mac命令行grep -A 3
-
简而言之,对于多个“重复的”匹配结果,ubuntu中的grep -A会把它们视为一个group(假如两个"--"中间的内容为一个group的话);而mac中的grep -A会将每一个匹配结果视为一个group。
-
扩展:在ubuntu上我可以通过如下面命令实现该log的简单去重(Mac上无法实现):
cat test.log | grep -A3 frame | grep -B4 "\-\-"
-
结果如下:
log字符串段落整理
注意到这样就能把每一帧对应的log取出来了。虽然最后一帧由于下面没有"--"分隔符没有获取到,但是由于log很长,中间丢弃几帧也是可以接受的。
网友评论