我想在目录中找到最新的子目录,并将结果保存到bash中的变量中。
这样的事情:
ls -t /backups | head -1 > $BACKUPDIR
有人可以帮忙吗?
答案 0 :(得分:38)
BACKUPDIR=$(ls -t /backups | head -1)
$(...)
在子shell中计算语句并返回输出。
答案 1 :(得分:15)
有一个简单的解决方案,仅使用ls
:
BACKUPDIR=$(ls -td /backups/*/ | head -1)
-t
按时间顺序(最新的第一个)-d
仅列出此文件夹中的项目*/
仅列出目录head -1
返回第一项在找到Listing only directories using ls in bash: An examination之前,我还不了解*/
。
答案 2 :(得分:4)
上述解决方案没有考虑从目录中写入和删除的文件,导致返回上层目录而不是最新的子目录。
另一个问题是此解决方案假定该目录仅包含其他目录而不包含正在写入的文件。
假设我创建了一个名为“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脚本中显示绝对路径,你总是可以使用这样的东西:
LOCALPATH=/backups
DIRECTORY=$(cd $LOCALPATH; find * -type d -prune -exec ls -d {} \; |tail -1)
答案 3 :(得分:1)
嗯,我认为这个解决方案效率最高:
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)
答案 4 :(得分: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"
它跳过符号链接,包括符号链接到目录,这可能是也可能不是正确的事情。它会跳过其他非目录。它处理名称中包含任何字符的目录,包括换行符和前导点。
答案 5 :(得分:0)
要使用ls -t
获取最新文件夹,如果您的目录不包含目录,则可能必须将文件与文件夹区分开来。使用简单的循环,您将获得安全,快速的结果,并允许在未来轻松实现不同的过滤器:
while read i ; do if [ -d "${i}" ] ; then newestFolder="${i}" ; break ; fi ; done < <(ls -t)
详细说明:
while read currentItemOnLoop # While reading each line of the file
do
if [ -d "${currentItemOnLoop}" ] # If the item is a folder
then
newestFolder="${currentItemOnLoop}" # Then save it into the "newestFolder" variable
break # and stop the loop
else
continue # Look for the next newest item
fi
done < <(ls -t) # Sending the result of "ls -t" as a "file" to the "while read" loop
谨防我精心制作的块上的continue
逻辑:
else
continue # Look for the next newest item
你不会使用它。我只是为了您的知名度而把它放在那里,因为在这种情况下它不会影响结果。
答案 6 :(得分:0)
您的“类似这样的东西”简直是热门:
BACKUPDIR=$(ls -t ./backups | head -1)
将您写的东西与我学到的东西相结合,也解决了我的问题。感谢您提出这个问题。
注意:我在Windows环境中的GitBash中运行名为./something.bash
的文件中的上述行。
答案 7 :(得分:0)
使用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查找(没有-printf
),您可以运行stat
来获取文件修改时间戳:
find . -mindepth 1 -maxdepth 1 -type d -exec stat -c '%Y %n' {} \; | sort -n | cut -d' ' -f2- | tail -n1
没有stat
的情况下,可以像this answer中那样,用[[
替换[
bash扩展名来使用纯shell解决方案。