带有bash脚本的`ls -l`的parse结果



我需要存储带有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

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

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

但是,它仅返回最后一行(即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

我需要按以下方式重命名:

-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

更好的方法是使用bash globbing

只列出所有文件

echo *

或与他们一起做某事

for file in *; do
  echo "$file" # or do something else
done

或递归使用bash 4

shopt -s globstar
for file in **/*; do
  echo "$file" # or do something else
done 

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

echo替换mv,以测试它的作用。另请注意,${file##*.}假定扩展名是最后一个阶段之后的所有内容,因此,如果您在Directory on中的file.tar.gz这样的文件将其变成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

例如。

> 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

说明

在Bash中您可以做这个

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

要删除所有内容(*)之前和包括最后一个时期,我做了以下

 extension=${file##*.} 

要删除包括和最后一个时期的所有内容,我在下面做过(在此处考虑最短的匹配,例如从右到左,例如*查找任何不遵循的文本,然后当它找到一个时期时,它会删除它整个部分)

filename=${file%.*}

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

filename=${filename##*/}

其他一些注释:

  • "$d/${filename}_${name}.$extension"变量可以具有_
  • "$d"/*直接在" $ d"
  • 中直接扩展到任何类型(常规,dir,symlink等)的每个文件

有什么问题
ls > myfile.txt

这只会列出文件名(没有其他)并将其发送到myfile.txt

如果您想走awk路线,只需做

ls -l | awk '{print $9}'

awk的默认操作是在空间上拆分字段 - 这将为每行的第9个字段打印…

如果您想用文件名做其他事情,则可以扩展尴尬脚本。例如,可以使用

创建带有这些文件名的数组
ls -l | awk '{a[NR]=$9}'

您可以在进一步处理中使用此数组(称为a)。如果处理需要awk以外的其他内容(从我认为的评论中),那么看起来像

的东西会更好
#!/bin/bash
for f in $1"/"*
do
if [ -d "$f" ] ; then
  ./listdir $f
else
  echo $f
fi
done

将其保存为当前目录中的listdir,您可以使用。

./listdir .

将列出整个目录,根据需要向下递归(随附完整的相对路径)。

如果您希望"从任何地方"可用(毕竟这是一个非常有用的命令),则将其放在路径中(并执行" rehash"命令,以便它将是"已知");然后,您不需要命令开始时的./

好问题!很高兴你问。解析ls的输出很少是正确的事情。有多种处理文件列表的方法。这取决于您想对他们做什么。

这是您可以做的一些示例。我使用touch作为示例命令。用您想做的任何命令替换为。

  1. 要通过多个文件运行命令,通常您可以简单地传递命令行上的所有文件。

    touch /var/myapp/*
    
  2. 在当前目录中的文件上循环:

    for file in *; do
        touch "$file"
    done
    
  3. 在另一个目录中循环循环:

    for file in /some/dir/*; do
        touch "$file"
    done
    
  4. 在这里和子目录中重命名为 *.txt到'*.bak'的文件:

    find . -name '*.txt' -exec mv {} {}.bak ;
    
  5. 在鲍勃的主目录中删除jpegs(该死的鲍勃和你流浪的眼睛):

    find ~bob/ -name '*.jpg' -delete
    
  6. 递归循环浏览文件,并向它们做复杂的事情:

    find /dir/to/search -print0 | while read -d $'' file; do
        echo "$file"
        touch "$file"
        if [[ -L $file ]]; then
            # $file is a symlink, do something special
        fi
    done
    

ls -l | awk '{split($0,array," ")} {print array[9]}'

ls -l | awk '{print $9}'

但是为什么不只是ls

相关内容

  • 没有找到相关文章