我可以用命令获取目录数量
ls -dtr */ | wc -l
但是我该如何专门删除N-1个目录,而保留最新目录呢?
答案 0 :(得分:4)
与通常对“一堆文件”进行的bash操作一样,您必须意识到空格和换行符的痛苦,这些痛苦和换行符可能合法地出现在文件名中。这些方法打破了基于xargs
/ for
的朴素方法,并且需要一些额外的限制。
许多工具支持-z
或-0
选项,这些选项使用NUL字节作为行分隔符而不是换行符-NUL可能永远不是文件名的一部分。
不幸的是,ls
不是其中之一,因此我们必须经过find
才能获取最新目录。
find . -maxdepth 1 -mindepth 1 -type d
这将获得当前目录中的所有目录。 (请注意:与您的ls -dtr */
相对,这还会也查找“隐藏”目录,即以.
开头的目录。添加! -name ".*"
可以避免这种情况。 )
-maxdepth 1
避免了递归,-mindepth 1
将父目录(.
)排除在列表之外。
find . -maxdepth 1 -mindepth 1 -type d -printf "%T+ %f\0"
这将列出目录及其时间戳,使用NUL而不是换行符进行行分隔。 (NUL永远不能成为文件名的一部分。)
find . -maxdepth 1 -mindepth 1 -type d -printf "%T+ %f\0" | sort -z
这使用NUL而不是换行符对结果进行排序。
find . -maxdepth 1 -mindepth 1 -type d -printf "%T+ %f\0" | sort -z | head -z -n -1
这将使用列表中的最后一个条目(最新目录及其时间戳)使用NUL而不是换行符来获取列表中的最后一个条目(最新目录及其时间戳)。
find . -maxdepth 1 -mindepth 1 -type d -printf "%T+ %f\0" | sort -z | head -z -n -1 | cut -z -d' ' -f 2-
使用NUL代替换行符作为行分隔符和空格作为字段定界符,这将从输出中过滤出第一个字段(时间戳)。
find . -maxdepth 1 -mindepth 1 -type d -printf "%T+ %f\0" | sort -z | head -z -n -1 | cut -z -d' ' -f 2- | xargs -0 rm -rf
使用NUL代替换行符来进行行分隔,这将为每个条目调用rm -rf
。
答案 1 :(得分:2)
这是一个纯Bash解决方案:
shopt -s nullglob # Globs that match nothing expand to nothing
shopt -s dotglob # Globs include files whose names start with '.'
newest_dir=
for sdir in */ ; do
dir=${sdir%/} # Remove slash to enable a symlink check
[[ -L $dir ]] && continue # Skip symlinks to directories
if [[ -z $newest_dir ]] ; then
newest_dir=$dir
elif [[ $dir -nt $newest_dir ]] ; then
echo rm -rf -- "$newest_dir"
newest_dir=$dir
else
echo rm -rf -- "$dir"
fi
done
它以当前形式仅打印命令以删除旧的子目录。删除echo
以使其起作用。
答案 2 :(得分:1)
使用tail
:
ls -dt */ | tail -n +2 | while read dirName; do rmdir "$dirName"; done
在将-n
的{{1}}的{{1}}选项指定为tail
时,它将跳过第一行。
这将列出按日期排序的目录,跳过最近的目录并保留其余的目录,这些目录将被删除。您可以在用例之后将+
替换为rmdir
。
您可以尝试:
rm -rf
输出:
mkdir test && cd test
for i in {1..100}; do mkdir subdir-$i; done
ls -dt */ | tail -n +2 | while read dirName; do rmdir "$dirName"; done
ls
编辑:如果任何目录名称包含换行符,则由于subdir-100
,该方法将失败。在这种情况下,请参阅@DevSolar的答案以获取更完整的答案。
答案 3 :(得分:0)
很多方法,这是另一种方法。 :)
rm -rf `ls -1dt * | tail -n +2 | tr '\n' ' '`
首先,ls -1dt *
仅列出按修改时间排序的所有目录,每行一个。然后tail -n +2
删除第一个,最近修改的。然后tr '\n ' '
将它们全部放在一行中。然后是rm -rf
目录。