我需要使用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
答案 0 :(得分:5)
更好的方法是使用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
更新以获取目录名称并将其附加到其中的所有文件
将mv
替换为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
e.g。
> 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,符号链接等...)答案 1 :(得分:3)
好问题!很高兴你问。解析ls
的输出很少是正确的。有多种方法可以处理文件列表。这取决于你想用它们做什么。
以下是您可以执行的一些示例。我使用touch
作为示例命令。用你想做的任何命令或命令替换它。
要在多个文件上运行命令,通常只需在命令行上传递所有文件。
touch /var/myapp/*
循环遍历当前目录中的文件:
for file in *; do
touch "$file"
done
循环遍历另一个目录中的文件:
for file in /some/dir/*; do
touch "$file"
done
要在此处和子目录中将名为*.txt
的文件重命名为'* .bak':
find . -name '*.txt' -exec mv {} {}.bak \;
删除Bob主页目录中的JPEG(该死的Bob和你流浪的眼睛):
find ~bob/ -name '*.jpg' -delete
以递归方式循环文件并对它们执行复杂的操作:
find /dir/to/search -print0 | while read -d $'\0' file; do
echo "$file"
touch "$file"
if [[ -L $file ]]; then
# $file is a symlink, do something special
fi
done
答案 2 :(得分:1)
有什么问题
ls > myfile.txt
这只列出文件名(没有别的)并将它们发送到myfile.txt
如果您想要awk
路线,请执行
ls -l | awk '{print $9}'
awk
的默认操作是分割空间上的字段 - 这会打印每行的第9个字段......
如果你想用文件名做其他事情,你可以扩展你的awk脚本。例如,可以使用
创建具有这些文件名的数组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”命令以使其“已知”);那么在命令开头你不需要./
。
答案 3 :(得分:1)
ls -l | awk '{split($0,array," ")} {print array[9]}'
或
ls -l | awk '{print $9}'
但为什么不只是ls
?