メインコンテンツへ移動

よく使うシンプルなコマンド_bashノート2

無料2017-02-18#Tool#shell find#shell统计行数#shell拆分日志#shell查找文件#shell md5

よく使われるシンプルなシェルコマンドの記録

cat(concatenate)

ファイル内容の読み取り、表示、および結合を行います。

標準入力からの内容とファイルの内容を結合します:

echo 'from stdin' | cat - test.sh

cat コマンドでは - は標準入力を表します。

If file is a single dash (`-') or absent, cat reads from the standard input.

その他のよく使うオプション:

# 给文件内容添上行号
cat -n test.sh
# 把文件中的连续多个空行压缩成一个
cat -s test.sh

find

基本的なルール

ディレクトリツリーを下にたどり、条件に一致するものを検索して処理します。

# 列出当前目录下所有文件/文件夹、子文件/文件夹
find .
# 用\0分隔(文件路径里有换行符时有用)
find . -print0

# 通配符
find -name "*.js"
# 忽略大小写
find -iname "*.js"
# 多条件
find . \( -name "e*" -o -name "s*" \)
# 路径匹配
find ../tnode -path "*node*"
# 与-path一样,只是参数为正则表达式
find . -regex ".*/e.*h$"
# 忽略大小写
find . -iregex ".*/e.*h$"

# 否定参数(独立参数,可以配合-name/path/regex等用)
find . ! -iregex ".*/e.*h$"
# 例如排除路径含有node_modules的
find ../tnode ! -regex ".*node_modules.*"

# 指定目录深度,-maxdepth 1表示向下找1级(也就是..的孩子,不找孙子)
find .. -name "*.js" -maxdepth 1
# 也可以指定起始深度,-mindepth 2 -maxdepth 2表示只在..的孙子中找,不找儿子也不找孙子的儿子
find .. -name "*.js" -mindepth 2 -maxdepth 2
# 单独用-mindepth找超过指定深度的文件(找深路径lib)
find .. -regex ".*node_modules*.*.js$" -mindepth 20

ファイルタイプによる検索

# 指定文件/文件夹,-type f表示只输出文件
find ../tnode ! -regex ".*node_modules.*" -type f

P.S. 引数の順序は検索効率に影響します。例えば、深さを先にチェックしてからタイプでフィルタリングする方が高速です。

ファイルタイプと type 引数の値の対応関係:

普通文件:f
符号链:l
目录:d
面向字符的设备文件:c
面向块的设备文件:b
套接字:s
FIFO:p

時間による検索

各ファイルには3つのタイムスタンプがあります:

访问时间:-atime
修改时间:-mtime
变化时间:-ctime

引数の値は整数で、日数を表します。接頭辞として +(より大きい)や -(より小さい)を付けることができます。例えば:

# 找出父级目录中,昨天到现在访问过的文件
find .. -type f -atime -1

分単位のものもあります:

# -amin, -mmin, -cmin
find .. -type f -amin $((-1 * 60 * 24))

また、特定のファイルを基準にして、それよりも新しい(修正時刻がより近い)ファイルを検索することもできます:

# 找出父级目录中,比~/.bash_profile更新的文件
find .. -type f -newer ~/.bash_profile

ファイルサイズによる検索

# 当前目录下大于1K的文件
find . -type f -size +1k

b(ブロック)、c(バイト)、w(ワード)、kMG の単位をサポートしています。前の3つは小文字、後ろの2つは大文字であることに注意してください。これは split などの他のコマンドでも一般的です。

その他の使い方

# 查找并删除
find . -type f -name "*.tmp" -delete
# 匹配文件权限
find . -type f -perm 777 -print
find . -type f -user ayqy

-exec と組み合わせて他のコマンドを実行する:

# 查找并格式化输出
find . -type f -exec printf "file: %s\n" {} \;
# 查找并备份
find . -type f -mtime +7 -exec cp {} bak/ \;

P.S. 末尾のバックスラッシュでエスケープされたセミコロンは -exec 引数の終了を示すために必須です。

-exec は1つのコマンドしか実行できません。複数のコマンドを実行する必要がある場合は、コマンドをファイルに書き込んでから実行します。例えば、バックアップコマンドを bak.sh に書き込みます:

#!/bin/bash
BAK_DIR=bak

if ! test -e "$BAK_DIR";
then
    mkdir "$BAK_DIR"
fi

for file in "$@";
do
    cp $file "$BAK_DIR"
done

それから検索して実行します:

find . -type f -mtime +7 -exec ./bak.sh {} \;

-prune で検索から除外する:

# 跳过.git和node_moudles目录
find . \( -name ".git" -prune \) -o \( -name "node_modules" -prune \) -o \( -type f -print \)

xargs

xargs コマンドは stdin から受け取ったデータを再フォーマットし、他のコマンドの引数として提供します。通常、パイプ演算子の直後に置かれます。基本形式:

cmd | xargs

複数行の入力を単一行の出力に変換する:

# 把换行符换成空格
cat test.sh | xargs

単一行の入力を複数行の出力に変換する:

# 按每行参数数量断开
echo "1 22 3 4 5 6 7" | xargs -n 3

-d で区切り文字を指定し、文字列の split を実現する:

# split
echo "1,2,3,4" | xargs -d ,
# `-d`参数是GUN扩展,FreeBSD和mac上没有,用其它方法完成
echo "1,2,3,4" | tr , ' '

-I で置換文字列を指定する:

# replace
echo "1 2 3 4" | xargs -n 1 -I {} find {}.txt

findxargs の組み合わせ:

# 查找并删除
find . -type f -name "*.tmp" -print0 | xargs -0 rm -f

ここでの -print0xargs -0\0 を区切り文字として使用し、temp file.tmp のようなデフォルトの区切り文字を含むファイル名が2つの引数に分割されるのを防ぎます。

コードの行数をカウントする:

find . -type f -name "*.sh" -print0 | xargs -0 wc -l

1つの引数に対して複数のコマンドを実行する:

# 与上面的replace作用相同
echo '1\n2\n3\n4' | (while read arg; do find $arg.txt; done)

xargs は各引数に対して1つのコマンドしか実行できませんが、サブシェル内でループ読み込みを使用すれば、ループ内で複数のコマンドを実行できます。

P.S. ここでの括弧はサブシェルを実行するためのものであり、前の条件付きグループ化とは異なります。括弧をエスケープしないでください。

tr(translate)

標準入力からの文字に対して置換、削除、圧縮を行い、文字列処理に使用します。

#  大小写转换
echo 'Ho Hoho hoho' | tr 'a-z' 'A-Z'

2つの文字セットのサイズが異なる場合、後ろのセットは最後の文字で補完されます。例えば:

# 结果是ABC XXX
echo 'abc xyz' | tr 'a-z' 'A-X'

P.S. 文字セットの定義形式は 開始文字-終了文字 です。結果が連続した文字シーケンスでない場合は、3つの独立した文字として扱われます。

注意:tr は入力された各文字に対してマッピングを行うだけで、文字列のマッチングや置換(string-level)ではなく、文字レベル(character-level)の操作です。

その他のよく使うオプション:

# -d删除字符
# 结果是a, a , 579
echo 'hohoa, hoa 123, 4579' | tr -d 'ho0-4'
# -c得到补集,一般与-d结合删除补集里的字符,只保留给定字符集合里的
# 结果是hohoho1234
echo 'hohoa, hoa 123, 4579' | tr -d -c 'ho0-4'
# -s压缩字符(把连续的重复字符换成一个)
# 结果是ha, ha
echo 'hhhhhha, ha' | tr -s 'a-z'

文字クラス(character class)をセットとして使用する:

# 大小写转换
echo '124abcX1' | tr '[:lower:]' '[:upper:]'

その他の文字クラスは man tr で確認できます。

md5sum, sha1sum

これら2つのコマンドはチェックサムを計算するために使用されます。例えば:

# 求文件md5
# 结果是`32个字符的16进制串 文件名`
md5sum test.sh

P.S. Mac にはデフォルトで md5sumsha1sum がないため、別途インストールが必要です。

MD5ファイルを使用して検証する:

# 用md5文件检查文件是否正确
md5sum -c file.md5

md5deep を使用してディレクトリの md5 を生成する(別途インストールが必要。sha1deep も同様):

# yum安装
yum install md5deep
# 求文件夹的md5
# -r递归,-l生成相对路径(默认是绝对路径)
md5deep -rl dir > dir.md5
# 用所有md5文件校验
md5sum *.md5

sort & uinq

sort コマンドは行をソートし、uniq は重複を排除します。通常、組み合わせて使用されます。例えば:

# 对file.txt内容每行按字典序排序,并去重
sort file.txt | uniq
# 或者
sort -u file.txt

デフォルトでは辞書順の昇順でソートされます。-n は数値順、-r は降順です:

# 如果字母数字都有,字母在前
sort -n file.txt
sort -r file.txt

その他のよく使うオプション:

# 检查文件内容是否有序,是否按数值序用-nC
# 返回值为0,表示有序
sort -C file.txt; echo $?
# 按第2列排序
sort -k 2 file.txt
# 按第2个字符到第5个字符排序
sort -k 2,5 file.txt
# 用\0作为分隔符(通过管道结合其它命令时有用)
sort -z file.txt
# 忽略前导空白字符
sort -b file.txt

uniq コマンドはソート済みの入力に対してのみ機能するため、通常は sort と組み合わせて使用します:

# 只显示唯一的行(出现多于1次的行都被滤掉)
uniq -u sorted.txt
# 统计各行出现次数
uniq -c sorted.txt
# 找出重复的行
uniq -d sorted.txt

重複排除時に key を指定することもできます:

# -s跳过前几个字符,-w指定key的长度
uniq -s 3 -w 2 sorted.txt

P.S. Mac には -w オプションがありません。

split

split コマンドは大きなファイルを分割するために使用されます。例えば:

# 把data.txt分割成1k的多个文件
split -b 1k data.txt

デフォルトでは xaa, xab, xac... のようなファイル名が生成されます。デフォルトではサイズで厳密に分割されるため、行が途切れたり、1つの漢字が分断されたりすることがあります。

生成されるファイル名は手動で指定できます。最後の引数は接頭辞で、デフォルトは x です。-a で接尾辞の長さを指定します。その他のオプションは man split を確認してください。

行数でファイルを分割することもできます:

# 每个文件10行,文件名为`small.aa, small.ab, small.ac...`
split -l 10 test.sh 'small.'

P.S. あんなコマンドがあったとは。当時 SQL のバックアップファイルを分割するために、わざわざ大きなファイルを編集できるテキストエディタを探して手動で分割していました...

P.S. もう一つのより強力なファイル分割コマンドは csplit です。ログファイルの分割によく使われ、特定のテキスト内容が存在するかどうかを条件に分割できます。

その他のテクニック

一時ファイルの名前付け

Ubuntu や Debian には tempfile コマンドがあり、一時ファイル名(ランダムな文字列)を生成します。他の環境では RANDOM 環境変数や現在のプロセス ID を使用できます:

# 取RANDOM环境变量的值
$RANDOM
# 取当前进程id
$$

文字列の抽出

%, %%, #, ## 演算子は強力な文字列抽出機能を提供します:

file=logo.png
# 提取文件名
filename=${file%.*}
echo filename:$filename
# 提取扩展名
ext=${file##*.}
echo ext:$ext

使い方は以下の通りです:

# 从var的值中删掉%右侧通配符所匹配的字符串,从右边向左匹配
${var%.*}
# %%贪婪匹配,会找出最长串,%匹配最短串
${var%.*}

# 从var的值中删掉#右侧通配符所匹配的字符串,从左向右匹配
${var#*.}
# 对应的贪婪匹配
${var##*.}

拡張子の抽出には ##(貪欲マッチング)を使用すべきです。file.txt.md5 のようなファイル名には複数の . が含まれているためです。

コメント

コメントはまだありません

コメントを書く