获取Bash中变量的最新目录
我想在一个目录中找到最新的子目录,并将结果保存到bash中的变量中 大概是这样的:获取Bash中变量的最新目录,bash,Bash,我想在一个目录中找到最新的子目录,并将结果保存到bash中的变量中 大概是这样的: ls -t /backups | head -1 > $BACKUPDIR LOCALPATH=/backups DIRECTORY=$(cd $LOCALPATH; find * -type d -prune -exec ls -d {} \; |tail -1) 有人能帮忙吗 BACKUPDIR=$(ls -td /backups/*/ | head -1) $(…)对子shell中的语句求值并返
ls -t /backups | head -1 > $BACKUPDIR
LOCALPATH=/backups
DIRECTORY=$(cd $LOCALPATH; find * -type d -prune -exec ls -d {} \; |tail -1)
有人能帮忙吗
BACKUPDIR=$(ls -td /backups/*/ | head -1)
$(…)
对子shell中的语句求值并返回输出。上述解决方案不考虑从目录中写入和删除文件等情况,导致返回的是上层目录而不是最新的子目录
另一个问题是,此解决方案假定该目录仅包含其他目录,而不包含正在写入的文件
假设我创建了一个名为“test.txt”的文件,然后再次运行此命令:
echo "test" > test.txt
ls -t /backups | head -1
test.txt
结果显示test.txt,而不是上次修改的目录
建议的解决方案“有效”,但仅在最佳情况下有效
假设最大目录深度为1,更好的解决方案是使用:
find /backups/* -type d -prune -exec ls -d {} \; |tail -1
只需将“/backups/”部分替换为实际路径
如果要避免在bash脚本中显示绝对路径,可以始终使用以下内容:
ls -t /backups | head -1 > $BACKUPDIR
LOCALPATH=/backups
DIRECTORY=$(cd $LOCALPATH; find * -type d -prune -exec ls -d {} \; |tail -1)
要使用
ls-t
获取最新文件夹,如果目录中不只有目录,则可能需要区分文件和文件夹。使用一个简单的循环,您将获得安全、快速的结果,并允许在将来轻松实现不同的过滤器:
while read i ; do if [ -d "${i}" ] ; then newestFolder="${i}" ; break ; fi ; done < <(ls -t)
你不会用它的。我把它放在那里只是为了你的可见性,因为在这种情况下它不会影响结果。好吧,我认为这个解决方案是最有效的:
path="/my/dir/structure/*"
backupdir=$(find $path -type d -prune | tail -n 1)
解释为什么这会好一点:
我们不需要子shell(除了用于将结果输入bash变量的子shell)。
我们不需要一个无用的-exec ls-d
在find
命令的末尾,它已经打印了目录列表。
我们可以很容易地改变这一点,例如排除某些模式。例如,如果您想要第二个最新目录,因为备份文件首先写入同一路径中的tmp目录:
backupdir=$(find $path -type -d -prune -not -name "*temp_dir" | tail -n 1)
这是一个纯Bash解决方案:
topdir=/backups
BACKUPDIR=
# Handle subdirectories beginning with '.', and empty $topdir
shopt -s dotglob nullglob
for file in "$topdir"/* ; do
[[ -L $file || ! -d $file ]] && continue
[[ -z $BACKUPDIR || $file -nt $BACKUPDIR ]] && BACKUPDIR=$file
done
printf 'BACKUPDIR=%q\n' "$BACKUPDIR"
它跳过符号链接,包括指向目录的符号链接,这可能是正确的,也可能不是正确的。它跳过其他非目录。它处理名称包含任何字符的目录,包括换行符和前导点。有一个简单的解决方案,只需使用
ls
:
BACKUPDIR=$(ls -td /backups/*/ | head -1)
按时间排序的订单(最新优先)-t
仅列出此文件夹中的项目-d
仅列出目录*/
返回第一项head-1
*/
你的“类似这样的东西”几乎是一部畅销书:
BACKUPDIR=$(ls -t ./backups | head -1)
把你写的和我学到的结合起来也解决了我的问题。谢谢你提出这个问题
注意:我在Windows环境中的GitBash中运行了上面的一行,文件名为
/something.bash
,使用GNU find,您可以获得带有修改时间戳的目录列表,对该列表排序并输出最新的:
find . -mindepth 1 -maxdepth 1 -type d -printf "%T@\t%p\0" | sort -z -n | cut -z -f2- | tail -z -n1
还是换行分隔
find . -mindepth 1 -maxdepth 1 -type d -printf "%T@\t%p\n" | sort -n | cut -f2- | tail -n1
使用POSIX find(没有-printf
),如果有,可以运行stat
,以获取文件修改时间戳:
find . -mindepth 1 -maxdepth 1 -type d -exec stat -c '%Y %n' {} \; | sort -n | cut -d' ' -f2- | tail -n1
如果没有
stat
,则可以使用纯shell解决方案,将[[
bash扩展替换为[
如中所示。尽管该解决方案已被接受,且投票率较高,但仍存在一些问题。如果目录中的最新项不是目录,则该解决方案不起作用。如果最新子目录的名称以“.”开头,则该解决方案不起作用。如果最新子目录的名称包含换行符,则该解决方案不起作用。投诉关于ls
的使用。有关处理ls
输出的危险性的详细说明,请参阅。尽管有升级投票,但此解决方案不起作用。find/backups/*-type d-prune-exec…
按shell展开/backups/*
时生成的顺序处理目录。顺序是确定的由名称而不是时间戳来终止。列出的最后一个目录通常不是最新的目录。在回答pjh对接受答案的评论时,“如果最新目录以“.”开头,则不起作用”,这也与我的答案有关。如果要包括以开头的文件夹。(但排除./and../)您可以将ls更改为:ls-td/backups/{.[^.],}?*/这主要是我自己的参考。使用--quoting style=shell escape似乎解决了我提出的ls的许多问题,这不是对文件夹进行排序。这是因为它遇到的问题与上的注释中描述的问题相同。这是唯一不会对有效文件任意中断的解决方案。