我正在尝试编写一个简单的bash脚本来计算目录中的文件数,然后将名为file <#files>的新文件添加到目录的末尾.我目前的尝试是:
name="out"
num=$(ls -l|wc -l)
echo foo > "${name}${num}"
Run Code Online (Sandbox Code Playgroud)
但是,这给了我一堆空格,产生了文件名out 12.为什么会出现空格,如何在不创建空格的情况下连接这些字符串?
在OS X(和一般类似BSD的系统)上,wc -l左空间将数字填充到8个字符,例如_______7(_出于技术原因在此处表示空格).
(如果你使用wc的输出不带引号用echo-例如 echo $(wc -l <<<'dummy'),你将不会看到填充,因为shell会'吃’的前导空格;如果双引号的命令替换,你会看到他们: echo "$(wc -l <<<'dummy')"
也就是说,出于稳健性和性能的原因,你最好ls不要wc同时使用它们.使用globbing捕获数组中的所有文件名并使用该数组的元素计数:
name='out'
files=( * ) # collect all filenames in array
echo foo > "${name}${#files[@]}" # use array-element count
Run Code Online (Sandbox Code Playgroud)
注意:默认情况下,*将不包括隐藏的物品,就像OP的ls命令(因为它不包括-A或-a).
使用shopt -s dotglob包括隐藏的项目太多.
此外,如果根本没有匹配的项目,Bash将按原样返回模式,即*; 让Bash返回空字符串,使用shopt -s nullglob.
通常,如果您确实发现需要从命令输出和/或Bash变量修剪前导和尾随空格:
要修剪存储在Bash变量中的值,请使用read:
# Single-line value:
val=' a b '
read -r val <<<"$val" # $val now contains 'a b'
# Multi-line value:
# Note: Trims leading and trailing whitespace including newlines, but
# preserves *any* interior whitespace, including empty and all-whitespace lines.
val=$'\n \t one\n \ntwo\n \n'
read -r -d '' val <<<"$val" # $val now contains $'one\n \ntwo'
Run Code Online (Sandbox Code Playgroud)要将命令输出作为管道的一部分或stdin/a 文件中的行修剪:
如果要修剪的值没有内部空白,或者你想要确保/不介意内部空白被标准化为每个单独的空格,则管道xargs(这是有效的,因为xargs在将输入解析为单词后,将它们传递给echo默认实用程序 - 没有shell参与); 结果始终是一个单一的输出线 ; 警告:xargs删除嵌入的引号和\实例,除非你\- 它们:
val=$(ls | wc -l | xargs) # $val now contains trimmed count
Run Code Online (Sandbox Code Playgroud)如果保留线内部空白是重要的,请使用sed; 注意, -不同于read -r d ''以上-这是一个基于LINE-溶液,所以输入线的数量将被保留,包括前缘和后空或全部空白线,具有所有空白线修剪到空的人(假定GNU桑达或BSD SED):
echo $'\nfoo \n \n bar \n' | sed -E 's/^[[:blank:]]+|[[:blank:]]+$//g'
# -> $'\nfoo\n\nbar'
Run Code Online (Sandbox Code Playgroud)简化方案:使用以下方法从值中删除所有空格tr:
单行/每行:
tr -d '[:blank:]' <<<$' a b c \n foo ' # -> $'abc\nfoo\n'
Run Code Online (Sandbox Code Playgroud)全球,包括换行:
tr -d '[:space:]' <<<$' a b c \n foo ' # -> 'abcfoo'
Run Code Online (Sandbox Code Playgroud)