我有一个 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
.