shell - BruceDai003/tech_blog GitHub Wiki

google Shell风格指南


参考链接

find


find . -type f -name "*.conf"
find path/to/dir -name "*.cc" -o -name "*.cpp" (-o的意思是or)
find . -type f -name "*sgemm*" | xargs wc -l # 搜索后,显示每个文件有多少行
find src -name "*.cpp" -exec ls -a {} + # 这一句是啥意思,我忘了备注了,之后查到后再备注。。。
find <path> -regextype egrep -regex '.*file([0-5][0-9]|6[0-7])\.txt' # 找到0~67的后缀的
find your-directory/ -name 'A*[0-9][0-9]' -delete

找出当前目录下所有log文件,且不是bert*.log的,删除掉

find . -type f -name '*.log' -not -name 'bert*.log' -delete

找出所有包含b的文件名,但是不在.git文件夹下的:

find -path ./git -prune -o -type f -name '*b*' -print

过滤多个文件夹

$ find / -path /foo/bar/baz  -prune  -o \
         -path /abc/def      -prune  -o \
         -path /usr/include  -prune  -o \
         -print

`ls **/*.cpp **/*.h`

如果已经有了一个文件列表(每个文件单独一行)位于my_file中,要在当前目录下查找这些文件,并且把找到的结果存入outputfile中:

find . | fgrep -f my_file > outputfile

find找出在一段时间内修改过的文件

  1. 找出过去5分钟内修改过的
find . -cmin -5

注意,是-5代表过去5分钟内;如果是5,就是准确的5分钟前修改过的;如果是+5,就是大于5分钟之前修改过的。 2. 找出过去7天内修改过的

find . -ctime -7

如何把一个文件夹Downloads下的文件都移动到另外一个文件夹Videos底下?

  1. 移动所有文件包括子文件夹
mv -v Downloads/* Videos/

# 或者用,如果遇到同名的,也会自动重命名
find /src/dir -type f -exec mv --backup=numbered -t /dst/dir {} +
  1. 移动所有文件(不包括文件夹):
find Downloads/ -type f -print0 | xargs -0 mv -t Videos
  1. 移动Downloads底下所有的文件,但是不包括子文件夹下的文件:
find Downloads/ -maxdepth 1 -type f -print0 | xargs -0 mv -t Videos

注意,上面的-maxdepth 1表明find只会搜索Downloads文件夹下一层,你也可以指定其他数字。

怎样统计每一个目录底下的文件个数?

find . -type f | cut -d/ -f2 | sort | uniq -c
注释:
find . -type f to find all items of the type file, in current folder and subfolders
cut -d/ -f2 to cut out their specific folder
sort to sort the list of foldernames
uniq -c to return the number of times each foldername has been counted

另外,查找一个变量中是否包含某一个文件的操作可以如下:

find ${PATH//:/\/ } -name 'file'

Grep


在当前目录下,搜索只要小写的generate单词的指定后缀的文件。

grep -wrn --include=\*.{cc,cu,cuh,h} "generate"

类似的,也可以去掉要搜索的后缀

grep -wrn --exclude=*.{md,bzl,proto,pbtxt} "generate" .
grep "\<hub\>" /usr/dict/words
grep -wrn --include=\*.{cc,cu,cuh,h} --exclude-dir={util,summary} "generate" .

搜索多个patterns:grep支持3种regex syntaxes: Basic, Entended, Perl-compatible.

grep 'pattern\|pattern2' file 这是basic
grep -E 'pattern1|pattern2' file 这是Entended

在算子批量测试的时候,会输出日志文件到logs文件夹中,我需要获取哪些文件里不包含PASSED字样的,如何做到?

grep -riL "PASSED" .

去掉文件中的注释行和空行,打印出来

grep -E -v "^#|^$" file

其中-E是使用regexes, -v是获取相反的matches。

使用grep过滤包含以level开头或者ci开头的shell文件

ls *.sh | grep -v -e 'level*' -e 'ci*'
# -v 是inverts the match
# -e 是allows for multiple search patterns
# 如果用-F,是matches by literal strings( instead of regex)

# 也可以放到一起,注意要escape the pipe
ls *.sh | grep -v 'level*\|ci*'

How to save terminal output to a file?


SomeCommand > SomeFile.txt 

append:
SomeCommand >> SomeFile.txt

if want stderr as well:
SomeCommand &> SomeFile.txt  
SomeCommand &>> SomeFile.txt

if only want stderr:
command 2> output.txt
command 2>> output.txt

both stderr and output displayed on the console and in a file:
SomeCommand 2>&1 | tee SomeFile.txt

Redirect:
command >file 2>&1 输出stderr和stdout到file

查看有哪些大的文件

便于删除无用数据等,比如ixUmd.log会变得很大,尤其是training的时候

du -hsx * | sort -rh | head -10
du command -h option : display sizes in human readable format (e.g., 1K, 234M, 2G).
du command -s option : show only a total for each argument (summary).
du command -x option : skip directories on different file systems.
sort command -r option : reverse the result of comparisons.
sort command -h option : compare human readable numbers. This is GNU sort specific option only.
head command -10 OR -n 10 option : show the first 10 lines.

遇到一个情况,在当前目录下有很多coco_train.record*的文件,另外还有一个文件夹raw-data,里面有很多原始的数据,包括压缩包,解压后的一些目录和文件等,很大。 比如,我现在想统计当前目录下的coco_train.record*文件一共有多大,怎么做?

find . -type f -name 'coco_train.record*' -exec du -ch {} + | grep total

顺便熟悉了一下-exec {} + 用法: 使用-exec/execdir 必须配合;或者+来表示命令的结束。两者的区别是: ;会对前面得到的结果中每一个分别执行命令,而+是对整个结果一起执行一个命令。 例子:

$ find /etc/rc* -exec echo Arg: {} ';'
Arg: /etc/rc.common
Arg: /etc/rc.common~previous
Arg: /etc/rc.local
Arg: /etc/rc.netboot

$ find /etc/rc* -exec echo Arg: {} '+'
Arg: /etc/rc.common /etc/rc.common~previous /etc/rc.local /etc/rc.netboot

所以上面那句也可以使用:

du -ch coco_train.record-000*  | grep total

''' find Source/ -type f -name '*.CR2' -print0 | rsync --dry-run -av --files-from - --from0 . remote@server:/Storage/ ''' Remove --dry-run when you're happy with what is planning to do.

apt相关命令


大多数的标准的软件都会以一个包的形式存在。可以用以下命令搜索,比如:

apt-cache search fftw
sudo apt-get install libfftw3-dev

scp命令


从服务器下载单个文件
scp username@servername:/path/filename /tmp/local_destination
下载目录
scp -r username@servername:remote_dir/ /tmp/local_dir 
举例:
scp -r train_data [email protected]:/home/xx.xxx/tests

rsync命令


scp是相当于复制,黏贴,如果有的话是覆盖,比较耗时间,不智能。 rsync是复制,如果有重复的文件,会直接跳过,而且他自己的算法优化。

-v : verbose
-r : copies data recursively (but don’t preserve timestamps and permission while transferring data
-a : archive mode, archive mode allows copying files recursively and it also preserves symbolic links, file permissions, user & group ownerships and timestamps
-z : compress file data
-h : human-readable, output numbers in a human-readable format
--progress: show progress
--include
--exclude
--delete:If a file or directory not exist at the source, but already exists at the destination, you might want to delete that existing file/directory at the target while syncing
--max-size
--remove-source-files
--dry-run
举例:
rsync -avz rpmpkgs/ [email protected]:/home/
rsync -avzhe ssh --progress /home/rpmpkgs [email protected]:/root/rpmpkgs

rm


sudo rm -r !(*.tgz) # 删除除了tgz后缀的其他文件 如果要删除以5 ~ 9结尾的文件,比如:

$ ls
yolov3_ckpt_0.pth
yolov3_ckpt_1.pth
yolov3_ckpt_2.pth
yolov3_ckpt_3.pth
yolov3_ckpt_4.pth
yolov3_ckpt_5.pth
yolov3_ckpt_6.pth
yolov3_ckpt_7.pth
yolov3_ckpt_8.pth
yolov3_ckpt_9.pth
yolov3_coco.pth
yolov3_voc_init.pth
yolov3_voc_pretrain.pth

执行:

ls | grep -P ".*_[5-9].*" | xargs -d"\n" rm
$ ls
v2                 yolov3_ckpt_1.pth  yolov3_ckpt_3.pth  yolov3_coco.pth      yolov3_voc_pretrain.pth
yolov3_ckpt_0.pth  yolov3_ckpt_2.pth  yolov3_ckpt_4.pth  yolov3_voc_init.pth

Bash从文件路径中获取文件名

命令是basename,从路径中取出目录以及后缀名。

$basename OPTION NAME [SUFFIX]

例子:

path="/var/www/html/test.php"
name=$(basename "$path" ".php")
echo "$name"

这里用"$path"的原因是,防止path里面有空格存在

OPTION:
-a, --multiple:添加多个路径
-s, --suffix: 后缀 $basename -s .html kt.html

Bash脚本判断一个变量如果不是以某些字符串开头,则执行something


if [[ ! $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO)$ ]]; then 
  echo "Phone type must be nortel, cisco or nec."
fi

^ - match a string at the beginning of line
$ - match end
=~ - Bash's built-in regex comparison operator

在一个if判断里添加多个表达式,考虑使用,因为更morden的写法

for g in 1 2 3
do
    for c in 123 456 789
    do
        if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
        then echo "g = $g; c = $c; true"
        else echo "g = $g; c = $c; false"
        fi
    done
done

dmesg信息


dmesg -xT
-x: (decode) shows facility and level as human-readable prefixes
-T: Human readable timestamps
--follow: watching live events

dmesg | grep -E "memory|tty|dma"

wget命令

关于目录:

-nd: --no-directories,不创建任何层级目录,全都保存在当前目录下,重名的会在后缀上添加数字。
-nH: --no-host-directories, 禁止创建域名前缀目录。因为默认使用-r选项后,比如http://ai.iluvatar.cn/会创建一个ai.iluvatar.cn的域名父目录。
--cut-dirs=number: 忽略number个目录。通常配合-r使用。
比如,ftp://ftp.xemacs.org/pub/xemacs/,使用-r后,会保存在ftp.xemacs.org/pub/xemacs/。
即便前面的-nH可以取消掉ftp.xemacs.org/部分,但是你的目录里还是有pub/xemacs部分。
此时,可以配合使用--cut-dirs来控制你要的文件目录模样。
No options        -> ftp.xemacs.org/pub/xemacs/
-nH               -> pub/xemacs/
-nH --cut-dirs=2  -> .
-nH --cut-dirs=1  -> xemacs/
--cut-dirs=1      -> ftp.xemacs.org/xemacs/
注意,xemacs目录底下的子目录并不会被忽略掉,而是会被创建的。这也是改命令和-nd的区别。
-P prefix: --directory-prefix=prefix 添加目录前缀。
-np: --np-parent
wget使用代理的方法
For all users of the system via the /etc/wgetrc,
or for the user only with the ~/.wgetrc file:

use_proxy=yes
http_proxy=127.0.0.1:8080
https_proxy=127.0.0.1:8080

or via -e options placed after the URL:
wget ... -e use_proxy=yes -e http_proxy=127.0.0.1:8080 ...

压缩/解压缩tar 最基本的命令


tar cvf file.tar *.c
tar xvf file.tar [-C dst_dir]

tar cvfz file.tar.gz *.c
tar xvfz file.tar.gz

// 压缩后比gzip的大小更小,但是可能更耗时
tar cvfj file.tar.tbz *.c
tar xcfj file.tar.tbz

jlremote


使用10.201.40.22的jupyterlab 远程执行 jlremote(已经在服务器上使用了alias,可以自己去查看代码) 本地执行 ssh -CNL localhost:3456:localhost:3456 [email protected]

export to bash

添加到末尾

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/custom/path/

写到bashrc里:

echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/custom/path/' >> ~/.bashrc

随机选取文本打印

从一个文件中随机选择一些行,打印出来。

shuf -n 10 voc_train.txt

或者用awk脚本语言

cat voc_train.txt | awk 'BEGIN {srand()} !/^$/ { if (rand() <= .001) print $0}

随机选取大约0.1%的内容打印出来。这个是用固定大小的内存,而前面的shuf会占用更大内存。

crontab

可以用来定时执行命令

crontab -e

进入编辑器,在里面添加一条命令。 按照如下格式添加:

MIN HOUR DOM MON DOW CMD

其中:

Field    Description    Allowed Value
MIN      Minute field    0 to 59
HOUR     Hour field      0 to 23
DOM      Day of Month    1-31
MON      Month field     1-12
DOW      Day Of Week     0-6
CMD      Command         Any command to be executed.

*	any value
,	value list separator
-	range of values
/	step values
@yearly	(non-standard)
@annually	(non-standard)
@monthly	(non-standard)
@weekly	(non-standard)
@daily	(non-standard)
@hourly	(non-standard)
@reboot	(non-standard)

例子:

# This will execute the Full backup shell script (full-backup) on 10th June 08:30 AM.
30 08 10 06 * /home/maverick/full-backup

# 定时每天2:00删除Ix*.log文件。
0 2 * * * find /home/liwei.dai/tests/ -type f -name 'Ix*.log' -delete

crontab -l

查看目前添加的任务列表。

ps

搜索一个进程并直接结束该进程:

ps -ef | grep print_cuda.py | grep -v grep | awk '{print $2}' | xargs kill -9

删除某个用户的进程,甚至父进程。 先查看id对应的用户名

getent passwd

然后

ps -U $UID -u $UID u

execute multiple commands

A; B    # Run A and then B, regardless of success of A
A && B  # Run B if and only if A succeeded
A || B  # Run B if and only if A failed
A &     # Run A in background.

combinations:
(A && B) & # Run a in background, followed by b in background only if a worked

comm

比较两个已排序的文件,默认输出3栏,| unique to A | unique to B | In both | 可以使用-1, -2, -3以及组合来取消输出某一/几栏。 比如:

# 只输出a.txt中独有的
comm -23 <(sort a.txt) <(sort b.txt)

tr

tr stands for translate, it's a command line utility for translating or deleting characters. It supports a range of transformations including uppercase to lowercase, squeezing repeating characters, deleting specific characters and basic find and replace. It can be used with UNIX pipes to support more complex translation. Syntax:

$ tr [OPTION] SET1 [SET2]

Options -c : complements the set of characters in string.i.e., operations apply to characters not in the given set -d : delete characters in the first set from the output. -s : replaces repeated characters listed in the set1 with single occurrence -t : truncates set1

Examples:

# 1. Lowercase to uppercase
$ cat greekfile | tr "[a-z]" "[A-Z]"
$ cat greekfile | tr [:lower:] [:upper:]

# 2. white-space to tabs
$ echo "Welcome To GeeksforGeeks" | tr [:space:] '\t'

# 3. Translate braces into parenthesis
$ cat greekfile | tr '{}' '()' > newfile.txt

# 4. Squeeze repetition of characters using -s
$ echo "Welcome      To    GeeksforGeeks" | tr -s [:space:]

# 5. Delete specified chars using -d
$ echo "Welcome To GeeksforGeeks" | tr -d 'G'

# 6. Remove all digits
$ echo "My ID is ALL989" | tr -d [:digit:]

# 7. Complement the sets using -c option
$ echo "My ID is ALL989" | tr -cd [:digit:]

一些其他的选项:

  \NNN            character with octal value NNN (1 to 3 octal digits)
  \\              backslash
  \a              audible BEL
  \b              backspace
  \f              form feed
  \n              new line
  \r              return
  \t              horizontal tab
  \v              vertical tab
  CHAR1-CHAR2     all characters from CHAR1 to CHAR2 in ascending order
  [CHAR*]         in SET2, copies of CHAR until length of SET1
  [CHAR*REPEAT]   REPEAT copies of CHAR, REPEAT octal if starting with 0
  [:alnum:]       all letters and digits
  [:alpha:]       all letters
  [:blank:]       all horizontal whitespace
  [:cntrl:]       all control characters
  [:digit:]       all digits
  [:graph:]       all printable characters, not including space
  [:lower:]       all lower case letters
  [:print:]       all printable characters, including space
  [:punct:]       all punctuation characters
  [:space:]       all horizontal or vertical whitespace
  [:upper:]       all upper case letters
  [:xdigit:]      all hexadecimal digits
  [=CHAR=]        all characters which are equivalent to CHAR

IFS

IFS是Internal Field Separator的意思。 比如你要打印$PATH里面的每一个路径可以如下操作:

( IFS=:
  for p in $MANPATH; do
      echo "$p"
  done
)

fuser

可以查看占用device的进程,比如:

sudo fuser -v /dev/aip_bi*

pushd, popd, dirs

之前我都是用cd -来切换到之前的目录,实际上cd -中的-就相当于变量$OLDPWDpushdpopd都是对一个目录栈进行操作,而dirs是显示目录栈的内容。而目录栈就是一个保存目录的栈结构,该栈的栈顶永远都存放当前目录。

  1. dirs
dirs -v # 每行显示一条记录,同时显示index
dirs -c # 清空目录栈
  1. pushd 每次执行完pushd命令后,默认都会执行一个dirs命令来显示目录栈的内容。主要用法:
pushd $some_dir # 切到该目录,变成栈顶
pushd # 不加参数,交换栈顶2个位置。相当于cd -
pushd +n # 切换到目录栈中+n的位置,并将该目录以栈循环的方式推到栈顶。
  1. popd 类似pushd,只不过是出栈操作。
popd
popd +n

Extract sub-string

可以使用Parameter Expansion来完成。 比如:

a="someletters_12345_moreleters.ext"
b=${a:12:5}

这里12是offset(zero-based), 5是length。 如果想要提取其中的数字12345,可以:

tmp=${a#*_} # Remove prefix ending in "_"
b=${tmp%_*} # Remove suffix starting with "_"

其实也可以用这个cut来完成:

echo 'someletters_12345_moreleters.ext' | cut -d'_' -f 2

更一般性的:

INPUT='someletters_12345_moreleters.ext'
SUBSTRING=$(echo $INPUT| cut -d'_' -f 2)
echo $SUBSTRING

添加环境变量

比如我要对PATH添加一个路径,但是可能PATH这个路径本身都是不存在的。所以,不要使用如下方式:

PATH=$PATH:~/opt/bin
或者
PATH=~/opt/bin:$PATH

请使用:

PATH="${PATH:+${PATH}:}~/opt/bin" # appending
或者
PATH="~/opt/bin${PATH:+:${PATH}}" # prepending

因为这样不会在PATH变量本身是empty的情况下添加奇怪的:符号。

sudo 找不到cmake

在centos环境下,编译软件的时候,用cmake可以找到,sudo cmake提示找不到:

source /opt/rh/devtoolset-9/enable

输出到文件

          || visible in terminal ||   visible in file   || existing
  Syntax  ||  StdOut  |  StdErr  ||  StdOut  |  StdErr  ||   file   
==========++==========+==========++==========+==========++===========
    >     ||    no    |   yes    ||   yes    |    no    || overwrite
    >>    ||    no    |   yes    ||   yes    |    no    ||  append
          ||          |          ||          |          ||
   2>     ||   yes    |    no    ||    no    |   yes    || overwrite
   2>>    ||   yes    |    no    ||    no    |   yes    ||  append
          ||          |          ||          |          ||
   &>     ||    no    |    no    ||   yes    |   yes    || overwrite
   &>>    ||    no    |    no    ||   yes    |   yes    ||  append
          ||          |          ||          |          ||
 | tee    ||   yes    |   yes    ||   yes    |    no    || overwrite
 | tee -a ||   yes    |   yes    ||   yes    |    no    ||  append
          ||          |          ||          |          ||
 n.e. (*) ||   yes    |   yes    ||    no    |   yes    || overwrite
 n.e. (*) ||   yes    |   yes    ||    no    |   yes    ||  append
          ||          |          ||          |          ||
|& tee    ||   yes    |   yes    ||   yes    |   yes    || overwrite
|& tee -a ||   yes    |   yes    ||   yes    |   yes    ||  append

sed删除文件中末尾空格

The following command deletes all spaces and tabs at the end of each line in input.java.

sed -i 's/[[:space:]]*$//' input.java

If there are multiple files that need trailing whitespaces removed, you can use a combination of find and sed commands. For example, the following command deletes trailing whitespaces in all *.java files recursively found in the current directory as well as all its sub-directories.

$ find . -name "*.java" -type f -print0 | xargs -0 sed -i 's/[[:space:]]*$//'

bash转大小写

x="HELLO"
echo $x  # HELLO

y=${x,,}
echo $y  # hello

z=${y^^}
echo $z  # HELLO

用途:比如在一个函数内部,用$1获取入参时,可以支持大写的或者小写的入参。比如:

function run_1card_FPS()
{
	export CUDA_VISIBLE_DEVICES=7
	PREC=$1
	for BATCH_SIZE in ${BATCH_SIZE_LIST}
	do
		if [ ${PREC^^} != 'FP32' -o "${BATCH_SIZE}" != "512" ];then
			# ../../../../tools/reset.sh
			numactl --physcpubind=0-7  python3 ./launch.py --model resnet50 --precision ${PREC^^} --mode benchmark_training --platform BI1 --batch-size ${BATCH_SIZE} ${DATASET_DIR} --data-backend pytorch > ${LOG_DIR}/r50_1card_${PREC,,}_batch_${BATCH_SIZE}_fps.log 2>&1
		fi
	done
}

显示所有的users id

awk -F: '/\/home/ {printf "%s:%s\n",$1,$3}' /etc/passwd

centOS安装openssh服务

在centOS安装ssh服务,从而vscode可以连接

sudo yum install -y openssh-server
sudo ssh-keygen -A
sudo /usr/sbin/sshd &

Regex example

https://www3.ntu.edu.sg/home/ehchua/programming/howto/Regexe.html

⚠️ **GitHub.com Fallback** ⚠️