使用bash脚本解析`ls -l`的结果

Mat*_*teo 1 linux bash shell awk

我需要使用bash脚本存储目录中包含的每个文件的名称,并以某种方式处理它:

drwxrwxr-x  5 matteorr matteorr  4096 Jan 10 17:37 Cluster
drwxr-xr-x  2 matteorr matteorr  4096 Jan 19 10:43 Desktop
drwxrwxr-x  9 matteorr matteorr  4096 Jan 20 10:01 Developer
drwxr-xr-x 11 matteorr matteorr  4096 Dec 20 13:55 Documents
drwxr-xr-x  2 matteorr matteorr 12288 Jan 20 13:44 Downloads
drwx------ 11 matteorr matteorr  4096 Jan 20 14:01 Dropbox
drwxr-xr-x  2 matteorr matteorr  4096 Oct 18 18:43 Music
drwxr-xr-x  2 matteorr matteorr  4096 Jan 19 22:12 Pictures
drwxr-xr-x  2 matteorr matteorr  4096 Oct 18 18:43 Public
drwxr-xr-x  2 matteorr matteorr  4096 Oct 18 18:43 Templates
drwxr-xr-x  2 matteorr matteorr  4096 Oct 18 18:43 Videos
Run Code Online (Sandbox Code Playgroud)

使用以下命令,我能够ls -l在所有空格之间拆分结果,然后访问包含名称的最后一个元素:

ls -l | awk '{split($0,array," ")} END{print array[9]}'
Run Code Online (Sandbox Code Playgroud)

但是它只返回最后一行(即Videos),所以我需要在ls -l命令返回的所有行上迭代它.

  • 我怎样才能做到这一点?
  • 有没有更好的方法来解决这个问题?

添加部分

更具体地说明我需要做什么:

对于目录中包含的所有文件,如果它是文件,我将不做任何事情,如果它是一个目录,我应该将目录的名称附加到它包含的所有文件.

假设视频目录中包含以下文件:

-rwxr-xr-x  2 matteorr matteorr  4096 Oct 18 18:43 video1.mpeg
-rwxr-xr-x  2 matteorr matteorr  4096 Oct 18 18:43 Video2.wmv
Run Code Online (Sandbox Code Playgroud)

我需要将它们重命名如下:

-rwxr-xr-x  2 matteorr matteorr  4096 Oct 18 18:43 video1_Videos.mpeg
-rwxr-xr-x  2 matteorr matteorr  4096 Oct 18 18:43 Video2_Videos.wmv
Run Code Online (Sandbox Code Playgroud)

Rei*_*ase 5

更好的方法是使用bash globbing

只列出所有文件

echo *
Run Code Online (Sandbox Code Playgroud)

或者与他们做点什么

for file in *; do
  echo "$file" # or do something else
done
Run Code Online (Sandbox Code Playgroud)

或者以bash 4+递归递归

shopt -s globstar
for file in **/*; do
  echo "$file" # or do something else
done 
Run Code Online (Sandbox Code Playgroud)

更新以获取目录名称并将其附加到其中的所有文件

替换mv为a echo来测试它的作用.另请注意${file##*.},扩展名是最后一个句点之后的所有内容,因此如果您有一个类似于file.tar.gz目录的文件on,则下面会将其转换为file.tar_on.gz.据我所知,没有简单的方法来处理这个问题,但.如果你愿意,可以跳过多个文件)

#!/bin/bash
d="/some/dir/to/do/this/on"
name=${d##*/} #name=on
for file in "$d"/*; do
  extension=${file##*.} 
  filename=${file%.*}
  filename=${filename##*/}
  [[ -f $file ]] && mv "$file" "$d/${filename}_${name}.$extension"
done
Run Code Online (Sandbox Code Playgroud)

例如

> ls /some/dir/to/do/this/on
video1.mpeg  Video2.wmv
> ./abovescript
> ls /some/dir/to/do/this/on
video1_on.mpeg  Video2_on.wmv
Run Code Online (Sandbox Code Playgroud)

说明

在bash中你可以做到这一点

  • ${parameter#word} 删除最短匹配前缀
  • ${parameter##word} 删除最长的匹配前缀
  • ${parameter%word} 删除最短匹配后缀
  • ${parameter%%word} 删除最长匹配后缀

要删除*之前(包括最后一个句点)之前的所有内容(),我在下面做了

 extension=${file##*.} 
Run Code Online (Sandbox Code Playgroud)

为了删除包括和从上一个时期开始的所有内容,我在下面做了(想想这里最短的匹配是从右到左,例如从右到左*查找任何非周期文本,然后当它找到一个句点时它会删除整个部分)

filename=${file%.*}
Run Code Online (Sandbox Code Playgroud)

为了删除所有内容,包括最后一个/,我在下面做了.

filename=${filename##*/}
Run Code Online (Sandbox Code Playgroud)

其他一些说明:

  • "$d/${filename}_${name}.$extension"变量可以有,_所以我在这里切换了几个变量的语法,以使其工作
  • "$d"/* 直接在"$ d"扩展到任何类型的每个文件(regular,dir,symlink等...)