当我尝试在 bash 提示符中用 Tab 键完成文件名时,输出将是许多(> 100)个文件名,shell 会询问Display all <num> possibilities? (y or n)
我可以使用普通ls
命令复制此行为吗?
我有一个包含 >400k 文件的目录。意外地ls
访问此目录会导致 shell 长时间无响应,同时还会输出输出。Ctrl-C
并不能阻止洪水。
答案1
我的解决方案可能有点重,但谁知道呢。
问题是,为了做到这一点,您需要对文件进行计数......这通常是通过以下方式完成的:
$ ls | wc -l
现在,由于内容被写入管道,而不是 stdout,因此完成此操作所需的时间会少一些(写入终端需要一点时间,这在 400k 次调用后会变得很重要)write(2)
)。这可能仍然需要一些时间,但尽管如此,您可以通过一个简单的测试来实现这一点:
#!/bin/bash
LIMIT=1000
n=$(ls "$@" 2>/dev/null | head -n$LIMIT | wc -l)
if [ $n -ge $LIMIT ]; then
echo "This directory contains more than $LIMIT entries."
echo -n "Are you sure want to continue? (y/N) "
read confirm
if [ "$confirm" = "y" -o "$confirm" = "Y" ]; then
exec ls "$@"
fi
else
exec ls "$@"
fi
然后,只需在文件中设置一个别名.bashrc
,即可调用此脚本而不是/bin/ls
:
alias ls='/path/to/my_ls.sh --color=auto'
还要确保它已正确 chmoded:
$ chmod +x /path/to/my_ls.sh
编辑:我添加了一个调用head
,以便在输出行ls
之后终止。$LIMIT
这应该可以节省一些时间(并且实际上使它成为一个更好的解决方案timeout
);)
我建议的另一种方法是使用超时。如果ls
没有在 5 秒内完成,它应该停止并询问您是否确定。这是一个示例脚本(对多个命令有效,而不仅仅是ls
):
#!/bin/bash
TIMEOUT=5
if [ $# -le 0 ]; then
echo "Usage: $0 [command]"
exit 1
fi
# Try it silently for a few seconds...
timeout $TIMEOUT "$@" >/dev/null 2>&1
if [ $? -eq 124 ]; then
echo -n "Your command failed to run under "$TIMEOUT"s. "
echo -n "Retry without a timeout? (y/N) "
read confirm
if [ "$confirm" = "y" -o "$confirm" = "Y" ]; then
exec "$@"
fi
else
exec "$@"
fi
然后你可以设置一些别名,例如:
alias ls='/path/to/script.sh ls --color=auto'
alias grep='/path/to/script.sh grep --color=auto'
alias cat='/path/to/script.sh cat'
请注意,我正在测试,$? -eq 124
因为...
如果命令超时且未
--preserve-status
设置,则退出并显示状态 124。
看timeout(1)
了解更多信息。