Bash 脚本从 ls -l 结果中提取文件名

Bash 脚本从 ls -l 结果中提取文件名

我有一个 Bash 脚本,旨在查找在特定日期创建的文件。它的工作原理如下。

#!/bin/bash

LOCATION="/tmp/testfiles"
DATE="Jan 10"
COMMAND="ls -l ${LOCATION} | grep '${DATE}'"

for FILE in `eval $COMMAND`
do
    echo $FILE
done

它正在定位我期望的文件

-rw-rw-rw- 1 root root  9485 Jan 10 10:00 test01.log

但是 bash for 循环正在循环遍历 ls -l 命令的所有字段,所以我最终得到

-rw-rw-rw-
1
root
root
9485
Jan
10
10:00
test01.log

这是我不想要的。是否可以从 ls -l 命令中提取文件名,以防止循环处理所有字段。

在这种情况下我不能只使用 ls 因为我需要知道日期才能让 grep 工作。

附言。我知道不建议将命令存储到变量中,但我现在需要这样,我可能会在稍后阶段更改它。

答案1

这应该打印给定日期之间修改的文件的所有路径:

find . -type f -newermt '2018-01-17' ! -newermt '2018-01-18'

如果文件名不包含空格、制表符、换行符和通配符(并且您尚未修改$IFS),则在脚本中使用时应该有效:

FILES=$(find /your/path -type f -newermt '2018-01-17' ! -newermt '2018-01-18')

for file in $FILES; do
    echo "${file}"
done 

它将打印路径而不仅仅是文件名。

根据您想要对这些文件执行的操作,还可以考虑直接使用find -exec command.

答案2

ls几乎普遍强烈建议不要在 shell 脚本中使用任何形式的命令输出。即使您使用ls -1(这是一个数字,“一”)而不是ls -l,您也必须处理包含嵌入空格等的文件名。

相反,请使用该find命令,并带有-print0安全打印选项和-ctime限制特定文件创建时间的选项。

答案3

为了安全地执行此任务,您不应解析ls,并且应eval尽可能避免使用。在此建议中,我还保护代码免受文件名中的空格和奇怪字符的影响:

date="Jan 10 2017"
find -type f -newermt "$date" \! -newermt "$date + 1 day" -printf '%P\0' |
    while IFS= read -r -d $'\000' f;
    do
        echo ">> $f <<"
    done

如果您只想捕获文件名,则不需要循环while read,也可以使用find ... -printf "%P"不带尾随的\0.

相关内容