Shell命令行Tips整理【持续更新】

1. mkdir -p:递归创建文件夹
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名字进行排除。

  • 应用举例:


    14755769-4a5e660ad7f10744.png
    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组合使用,可以排除掉某些不想要的名字
14755769-ef24b0fcfc146094.png
image.png
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 实例学习
awk 'BEGIN {FS=" +|,";} {printf("%s','%.0f %.0f %.0f %.0f\n", $1,$2,$3,$4,$5);}' train_labels.csv

注意printf中要格式化输出空格,直接用空格即可。不需要用\0之类的

14755769-8e54c343fd6b4dce.png
转换结果

7. 拷贝目录
  • 场景:有时候在远程服务器上工作时,想要拷贝或者是远程拷贝一个目录给同事,但是可能同事比较在意这个目录结构以及脚本(不要小看了“结构”,很多组织有序的文件夹就是一个Python module~),但是不在意目录里面的数据集(可能有多个位置存放数据,且占空间较大)。也就是说,我希望拷贝整个目录结构,同时exclude掉不想要的pattern,如*.jpg,或者一些较大的模型权重,如.h5,但是又保留他们各自所在的子文件夹,以便让我的同事知道这个文件夹应该放数据集,那个文件夹应该放权重。如何快速做到这些?

  • 解决:只需要一句命令:rsync
    参考:https://stackoverflow.com/questions/4585929/how-to-use-cp-command-to-exclude-a-specific-directory/14789400#14789400?newreg=ebc0a9fd681045a3b061bc7aecf5cd07

  • 举例:


    14755769-698bb914b923c010.png
    原目录结构

为了给同事一个干净的文件夹,我不想拷贝以下内容: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中有很多其他有趣的答案,非常值得一看。

猜你喜欢

转载自blog.csdn.net/weixin_34390996/article/details/87228269