管道指令如何配合mv进行特殊文件的批量剪切

 本次任务:将某一目录下所有的显式文件(不包括文件夹)全部移到指定目录下。

情景:

  • 在root的home目录(~或/root)下有这些文件和目录(文件夹)

[root@localhost ~]# ll
total 132
-rw-------.  1 root root  2596 Apr 18 17:00 anaconda-ks.cfg
-rw-r--r--.  1 root root   392 Jun  2 21:54 another
-rw-r--r--.  1 root root   176 Sep 15  2007 bashrc
-rw-r--r--.  1 root root    22 Jun  7 15:57 catfile
-rw-r--r--.  1 root root  2872 Jun  7 18:37 col.man
-rw-r--r--.  1 root root    50 Jun  2 21:55 fiveten
drwxr-xr-x.  3 root root  4096 Apr 18 17:00 home
-rw-r--r--.  1 root root  1167 Jun  7 18:20 homefile
drwxr-xr-x. 22 root root  4096 Jun  2 19:23 initrd
-rw-r--r--.  1 root root 45509 Apr 18 17:00 install.log
-rw-r--r--.  1 root root 13217 Apr 18 16:59 install.log.syslog
-rw-r--r--.  1 root root  7122 Jun  7 18:17 last.list
-rw-r--r--.  1 root root    89 Jun  9 23:14 pay.txt
-rw-r--r--.  1 root root    97 Jun  9 21:14 printf.txt
-rw-r--r--.  1 root root   650 Jun  9 20:56 regular_express.txt
-rw-r--r--.  1 root root  1167 Jun  7 15:35 rootfile
drwxr-xr-x.  2 root root  4096 Jun 14 10:54 test

  • 由上面的输出可知,home,initrd,test为目录,我们要将所有除目录外的显示文件都剪切到test目录下。

方法一:

ll | grep '^-' | awk '{print $9}' | xargs -i mv {} ./test

分析:

ll(ls -l):列出当前目录下显式的文件和目录的详细信息。共有九个字段,其中第一个字段表示文档的属性,-:表示普通文件,d:表示目录文件。

|:竖线,Enter键上面的那个按键,该符号为管道,作用是管道符左边命令的输出就会作为管道符右边命令的输入。

grep '^-':提取出开头字符为‘-’的输出行。也即提取出显式普通文件,去掉目录,‘^word’表示待搜寻的字符串(word)在行首,grep按行为单位进行操作。

awk '{print $9}':该命令提取出文件的名称,通常在第九列。awk主要处理每一行的字段内的数据,默认的字段分隔符为空格键或TAB键可能导致提取错误)。而sed主要以行为单位处理数据。awk后面接两个单引号并加上大括号 {} 来设定想要对数据进行的处理动作,并且透过 print 的功能将字段数据列出来。

xargs -i mv {} ./test:将上一个命令输出的文件名构造成参数列表,传递给mv指令使用。至此所有的除目录外的文件都剪切到test/目录中了

xargs的用法之一是构造参数列表并运行命令,即将接收的参数传递给后面的command 命令执行由于mv,ls,cp不支持管道命令,所以可以配合xargs使用,达到相同的效果。-i -i 选项告诉 xargs 可以使用{}代替传递过来的参数, 建议使用-I(是i的大写字母I,不是数字1,也不是L的小写字母),其符合POSIX标准,由于mv的第一个参数为源文件,在这里{}的作用就是表示xargs处理后的参数传递到{}中供mv使用。所以也可写成:

[root@localhost ~]# ll | grep '^-' | awk '{print $9}' | xargs -I {} mv {} ./test 


[root@localhost ~]# man xargs

-I replace-str
              Replace occurrences of replace-str in the initial-arguments with
              names read from standard input.  Also, unquoted  blanks  do  not
              terminate  input  items;  instead  the  separator is the newline
              character.  Implies -x and -L 1.


执行结果如下:

[root@localhost ~]# ll | grep '^-' | awk '{print $9}' | xargs -i mv {} ./test
[root@localhost ~]# ls
home  initrd  test
[root@localhost ~]# cd test
[root@localhost test]# ls
anaconda-ks.cfg  catfile  homefile            last.list   regular_express.txt
another          col.man  install.log         pay.txt     rootfile
bashrc           fiveten  install.log.syslog  printf.txt

[root@localhost test]# ll
total 120
-rw-------. 1 root root  2596 Apr 18 17:00 anaconda-ks.cfg
-rw-r--r--. 1 root root   392 Jun  2 21:54 another
-rw-r--r--. 1 root root   176 Sep 15  2007 bashrc
-rw-r--r--. 1 root root    22 Jun  7 15:57 catfile
-rw-r--r--. 1 root root  2872 Jun  7 18:37 col.man
-rw-r--r--. 1 root root    50 Jun  2 21:55 fiveten
-rw-r--r--. 1 root root  1167 Jun  7 18:20 homefile
-rw-r--r--. 1 root root 45509 Apr 18 17:00 install.log
-rw-r--r--. 1 root root 13217 Apr 18 16:59 install.log.syslog
-rw-r--r--. 1 root root  7122 Jun  7 18:17 last.list
-rw-r--r--. 1 root root    89 Jun  9 23:14 pay.txt
-rw-r--r--. 1 root root    97 Jun  9 21:14 printf.txt
-rw-r--r--. 1 root root   650 Jun  9 20:56 regular_express.txt
-rw-r--r--. 1 root root  1167 Jun  7 15:35 rootfile
[root@localhost test]# cd ..
[root@localhost ~]# ll
total 12
drwxr-xr-x.  3 root root 4096 Apr 18 17:00 home
drwxr-xr-x. 22 root root 4096 Jun  2 19:23 initrd
drwxr-xr-x.  2 root root 4096 Jun 14 11:43 test

由上看到所有的除目录外的文件都移到test/目录下,如此看来功能都实现了,但是……

当文档名称中间有空格怎么办呢,由于awk命令的“缺陷”:默认以空格或TAB键为空格,会产生误判,

举例:

[root@localhost ~]# touch "f ile"
[root@localhost ~]# ls
anaconda-ks.cfg  col.man  homefile            last.list            rootfile
another          f ile    initrd              pay.txt              test
bashrc           fiveten  install.log         printf.txt

catfile          home     install.log.syslog  regular_express.txt

[root@localhost ~]# ll | grep '^-' | awk '{print $9}' | xargs -I {} mv {} ./test
mv: cannot stat `f': No such file or directory
[root@localhost ~]# ls
f ile  home  initrd  test

出现错误了,“f ile”文件没有被剪切过去。

解决方法:

ls -1 -F | grep -v [/$] | xargs -I {} mv {} ./test

解释:

ls -1 ,注意这里是数字1,作用是单列输出。-1     list one file per line

ls-F:根据文件、目录等信息在文件名或目录名最后给予附加数据结构,例如:

*代表可执行文件;/代表目录;=代表socket文件;|代表FIFO文件;@代表连接文件

-F, --classify
              append indicator (one of */=>@|) to entries


[root@localhost ~]# ls -1
f ile
home
initrd
test
[root@localhost ~]# ls -F
f ile  home/  initrd/  test/
[root@localhost ~]#

通过上面的一个任务熟悉了linux下管线,正规表达式,通配符,bash命令等的使用。


通配符和正规表达式的区别?

原文地址:https://www.cnblogs.com/cnsec/p/3789790.html