Linux 常用技巧

2013-03-09 linux

文本替换

命令行批量替换多文件中的字符串,常用有三种方法:Mahuinan 法、Sumly 法和 30T 法。

----- 查看所匹配的字符串
$ sed -n '/orig/'p *.txt 

----- Mahuinan法,用sed命令批量替换多个文件中的字符串
$ sed -i "s/orig/sub/g" "`grep orig -rl directory`"
解读:
    sed -i 选项表示原地替换,若只显示结果则用-e替换;
    g 表示全局,否则只替换第一个匹配字符串;
    grep -r 表示对目录递归调用;-l(L小写)列出匹配的文件。

----- Sumly法
$ perl -pi -e "s/China/Sumly/g" /www/*.htm /www/*.txt
解读:
    将www文件夹下所有的htm和txt文件中的"China"都替换为"Sumly"

----- 30T法
$ perl -pi -e 's/baidu/30T/g' `find /www -type f`
解读:
  将www文件夹下所有文件,不分扩展名,所有的"baidu"都替换为"30T"

注意,在 Mahuinan 中,为了防止文件名中存在空格,所以使用引号包裹。

install 和 cp 命令

两者都可以将文件/目录拷贝到指定的目录,不过 install 允许你控制目标文件的属性,常用于程序的 Makefile 文件。

install [OPTION]... SOURCE DIRECTORY
常用参数:
    -m, --mode=0700
        设定权限;
    -v, --verbose
        打印处理的每个文件/目录名称;
    -d, --directory
        所有参数都作为目录处理,而且会创建指定目录;
    -g, --group=mysql
        设定所属组,而不是进程目前的所属组;
    -o, --owner=mysql
        设定所有者,只适用于超级用户;
    -s, --strip
        使用strip命令删除文件中的符号表 (symbol table);
    -S, --suffix=exe
        指定安装文件的后缀;
    -p, --preserve-timestamps
        以源文件的访问/修改时间作为相应的目的地文件的时间属性;
    -t, --target-directory
        如果最后一个文件是一个目录并且没有使用-T,--no-target-directory选项,
        则将每个源文件拷贝到指定的目录,源和目标文件名相同;

使用 -d 选项时,如果指定安装位置为 /usr/local/foo/bar,一般 /usr/local 已存在,install 会直接创建 foo/bar 目录,并把程序安装到指定位置。

如果指定了两个文件名,则将第一个文件拷贝到第二个,

----- 安装目录,等价于mkdir /tmp/bin
$ install --verbose -d -m 0755 /tmp/bin

----- 安装文件,等价于cp a/e c
$ install -v -m 0755 a/e c

----- 安装文件,等价于mkdir -p a/b && cp x a/b/c
$ install -v -m 0755 -D x a/b/c

避免误删目录

今天就来聊聊 linux 下一个常见的问题:如何避免误删目录。下文会详细的讲述不同的场景下误删目录,以及相应的解决方案。

#--- 1. 变量为空导致误删文件,如果file为空或命令返回空
rm -rf /usr/sbin/$file
#--- 使用变量扩展功能,变量为空使用默认值或抛出异常退出
rm -rf /usr/sbin/${file:?var is empty}
#--- 人肉判断变量是否为空
[[ ${file} == "" ]] && echo 1
[[ -z ${file} ]] && echo 1

#--- 2. 路径含有空格导致误删文件
path="/usr/local /sbin"
rm -rf $path
#--- 变量加引号防止扩展
rm -rf "$path"

#--- 3. 目录或文件含有特殊字符导致误删文件,例如 "~"
#--- 变量加引号防止扩展
rm -rf "~"

#--- 4. cd切换目录失败,导致文件被误删
#--- 使用逻辑短路操作
cd path && rm -rf *.exe
#--- 检测path是否存在
[[ -d path ]] && echo 1

man

Linux 上的 manpage 是用 groff 语法编写的,实际上可以通过如下的命令查看:

zcat man.1.gz | groff -man -Tascii | more

其查找路径可以通过 man -w 命令查看,或者查看配置文件 /etc/man.config;很多帮助文档保存在 /usr/share/man 目录下,又按照不同类型保存不同的子目录下,例如 /usr/share/man/man1/mysqlshow.1.gz

如下是常见的查看命令:

----- 查看搜索路径
$ man -w
----- 显示man命令搜索到的第一个文件路径
$ man -w passwd
----- 显示所有匹配的man文档
$ man -aw passwd

----- 指定领域限制
$ man 5 passwd
$ man -S 1:2 passwd

----- 同命令whatis ,将在whatis数据库查找以关键字开同的帮助索引信息
$ man -f httpd
----- 同命令apropos 将搜索whatis数据库,模糊查找关键字
$ man -k httpd

换行处理

*nix 系统里,每行结尾只有 "<换行>",即 "\n" ;Windows 系统里面,每行结尾是 "<换行><回车>" ,即 "\n\r"

如果不进行转换,那么 *nix 系统下的文件在 Windows 里打开所有文字会变成一行;而 Windows 里的文件在 *nix 下打开的话,在每行的结尾可能会多出一个 ^M 符号。

要把文件转换一下,有两种方法:

  1. 命令 dos2unix test.file
  2. 去掉 "\r" ,用命令 sed -i 's/\r//' test.file

历史命令

----- 去除重复命令,包括不连续的命令,通过ignoredups去除连续重复的命令
export HISTCONTROL=erasedups

异常处理

Text file busy

执行复制时可能会报如上的错误,处理方式如下:

----- 查看文件被那个进程占用
# fuser youfile

如果有进程占用,确保进程无用直接 kill 掉。

杂项

shell 操作

----- 查看当前所有shell
$ chsh -l
$ cat /etc/shells

查看当前的 Shell ,可以查看 SHELL 变量,不过如果是通过 bash dash sh 等直接运行的话,那么 SHELL 不变,可以通过如下方式查看。

$ ps | grep $$ | awk '{print $4}'
$ echo $0
$ tom                                # 输入没有的命令

chsh -s /bin/dash 实际修改的是 /etc/passwd 文件里和你的用户名相对应的那一行,重启 Shell 后即可。

符号链接

当读取符号链接文件时,默认会重定向到指定的文件,可以通过 C 中的 readlink() 或者 readlink 命令查看符号链接文件中的内容。

----- 建立测试用符号链接
$ echo "just for test" > original.txt
$ ln -s original.txt symbol.txt

----- 读取并解析出源文件的绝对路径
$ readlink -f symbol.txt
----- 直接查看符号链接的内容
$ readlink symbol.txt

----- 复制时保持符号链接内容
$ cp -d symbol.txt copy.txt

硬链接

通过 ls -l 可以查看符号链接所引用的原文件,而对于硬链接则不能通过上述命令查看,可以通过如下方式查看所有的硬链接文件。

----- 查找文件对应的inode信息,包括其引用计数
$ ls -il

----- 根据inode信息找到所有的文件
$ find / -inum 33582147

注意:软链接能够跨越文件系统 (分区),硬链接不可以。