我需要在目录中找到最新的文件 我目前使用的是:
cd /mypath/ && ls -t | head -n1
问题是,我经常创建文件,有时, 在'相同'时间创建了2个文件,这意味着当我 执行上面的行我会错过其中一个文件。
有人可以帮忙吗?
答案 0 :(得分:0)
抱歉原来的混音。这是一个简短的脚本,可以在目录中找到最新的文件(作为第一个参数给出)。使用stat -c %Y
查找自纪元以来的秒数。然后与目录中的所有其他文件进行比较,如果时差(td
)小于10
秒,则输出文件名(您可以调整差异以满足您的需求)
尝试一下:
#!/bin/bash
path="${1:-.}" ## set path (default .)
[ "${path:(-1):1}" = '/' ] && path="${path%/}" ## strip trailing '/'
oldifs="$IFS" ## save old IFS, set to break on newline
IFS=$'\n'
fnarray=( $(ls -rt "$path" | tail -n5) ) ## read newest 5 into array
IFS="$oldifs"
for ((i=$((${#fnarray[@]} - 1)); i >= 0; i--)); do ## make sure newest is file
[ -f "${path}/${fnarray[i]}" ] && fn="${path}/${fnarray[i]}" && break
done
[ -d "$fn" ] && { echo "error: no file found in newest 5 entries"; exit 1; }
for i in "${path}"/*; do ## for each file in path
[ -f "$i" ] || continue ## if not a file skip
td=$(( $(stat -c %Y "$i") - $(stat -c %Y "$fn") )) ## time difference in sec
(( td < 0 )) && td=$(( td * -1 )) ## takes abs value
(( td < 10 )) && echo "$i" ## if less than 10 seconds, output file
done
exit 0
注意:我遇到的原始问题是由于目录中的最新条目可能是子目录(不需要)。由于ls ..| tail..
返回结果的方式,这提出了挑战。所以基本上我把最后5个作为黑客攻击(你应该设置一个5的初始尝试,如果fn
仍然是一个目录,将它增加两倍并再试一次......直到你用尽所有文件为止目录..或首先做一个简单的find /path/ -type f
以确保存在文件叹息,但这会完全模糊对最旧代码的测试。
我不喜欢解决方案的另一个问题是,在bash中比较stat
次并不是天生的快。所以这在大型目录上不会闪电般快。 (适用于&lt; 1000条目)。以完全相同的时间返回可能的最新文件是一个很好的挑战,没有我能找到的快速现成的解决方案。
对目标目录中所有条目进行迭代测试的完整实现,从最新的向后工作,找到第一个文件(不是dir)来比较时间,类似于以下内容。 注意:代码已经过测试,但可能仍有需要修复的极端情况:
#!/bin/bash
path="${1:-.}" ## set path (default .)
[ "${path:(-1):1}" = '/' ] && path="${path%/}" ## strip trailing '/'
[ -d "$path" ] || { ## validate path
echo "error: invalid path provided. '$path' not found."
exit 1;
}
declare -i n=5 ## initial entries to read into array if fn is directory
declare -i oldn=1 ## save index for increased loop efficiency
## get number of files in target path
nfiles=$(wc -l < <( find "$path" -maxdepth 1 -type f ) )
(( $nfiles < 1 )) && { ## test files present in path or exit
echo "error: no files found in target directory"
exit 1
}
oldifs="$IFS" ## save old IFS, set to break on newline
IFS=$'\n'
fn="${path}/$(ls -rt "$path" | tail -n1)" ## find most recent file
while [ -d "$fn" ]; do ## while fn is a directory
fnarray=( $(ls -rt "$path" | tail -n$n) ) ## read newest n entries into array
for ((i=$((${#fnarray[@]} - oldn)); i >= 0; i--)); do ## make sure newest is file
[ -f "${path}/${fnarray[i]}" ] && fn="${path}/${fnarray[i]}" && break
done
(( n == nfiles )) && break ## if all entries tried, bail
oldn=$n ## update oldn to skip next try
[ -f "$fn" ] && break || n=$(( n * 2 )) ## if file, done, else n=n*2
(( n > nfiles )) && n=nfiles ## if n > nfiles, n=nfiles
done
[ -d "$fn" ] && {
echo "error: something bad happened, no files found in target directory"
exit 1
}
IFS="$oldifs"
for i in "${path}"/*; do ## for each file in path
[ -f "$i" ] || continue ## if not a file skip
td=$(( $(stat -c %Y "$fn") - $(stat -c %Y "$i") )) ## time difference in sec
(( td < 0 )) && td=$(( td * -1 )) ## takes abs value
(( td < 10 )) && echo "$i" ## td less than X seconds, output filename
done
exit 0
不知何故,这似乎有点过分......
答案 1 :(得分:0)
似乎您不仅需要最新的文件,而且您希望仅报告每个新文件一次。以下脚本通过保留跟踪上次报告内容的$reftime
文件来实现此目的:
cd "$1"
reftime=/tmp/newest-file-name
next_file=
prev_file=$(cat "$reftime" 2> /dev/null)
while true; do
read -r filename
if [[ "$prev_file" ]]; then
[[ "$filename" = "$prev_file" ]] && break # we've gotten to reported files
else
[[ -z "$filename" ]] && break # we've read past the last file
fi
next_file="$filename"
done < <(ls -t)
if [[ "$next_file" ]]; then
# Update file $reftime with time and name of the file we're about to offer
echo "$next_file" > "$reftime"
touch -r "$next_file" "$reftime"
echo "$next_file"
fi