小编Gre*_*bet的帖子

为什么`find . -type f` 比 `find .` 花费的时间更长?

似乎find必须检查给定的路径是否与文件或目录相对应,以便递归地遍历目录的内容。

这是一些动机以及我在本地所做的事情,以说服自己find . -type f确实比find .. 我还没有深入研究 GNU 查找源代码。

所以我正在备份我$HOME/Workspace目录中的一些文件,并排除属于我的项目或版本控制文件的依赖项的文件。

所以我运行了以下快速执行的命令

% find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-and-dirs.txt
Run Code Online (Sandbox Code Playgroud)

find管道传输到grep可能是不好的形式,但它似乎是使用否定正则表达式过滤器的最直接方式。

以下命令仅包含 find 输出中的文件,并且花费的时间明显更长。

% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
Run Code Online (Sandbox Code Playgroud)

我编写了一些代码来测试这两个命令的性能(使用dashtcsh,只是为了排除 shell 可能产生的任何影响,即使不应该有任何影响)。的tcsh,因为他们基本上是相同的结果已被忽略。

我得到的结果显示了大约 10% 的性能损失 -type f

下面是程序的输出,显示了执行 1000 次各种命令迭代所花费的时间。

% perl tester.pl
/bin/sh -c find Workspace/ >/dev/null
82.986582

/bin/sh -c find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' …
Run Code Online (Sandbox Code Playgroud)

performance find gnu

15
推荐指数
1
解决办法
664
查看次数

避免单独向 shell 会话添加 ssh 密钥(带密码)

注意:在.<name of shell>rcssh 中添加几行并不能解决这里的问题,因为这个特定的 ssh 密钥有一个密码,并且不会消除继续输入它的需要。

所以我真的不明白ssh-agent引擎盖下是如何工作的。我只是使用ssh-agentssh-add ~/.ssh/id_rsa每次我需要添加一个密钥来访问一些远程资源。我已经添加了一次密钥,我不需要为同一个“shell 会话”再次添加它(“shell 会话”可能不是合适的行话)。

不幸的是,我一直在创建新的 shell 会话。我在 OS X 上的 tmux 下运行 zsh 并且有一个创造性地命名为id_rsa. 该 ssh 密钥具有与之关联的密码。

每次我启动一个新的 shell 时,我都必须执行以下操作

$ eval `ssh-agent`
$ ssh-add ~/.ssh/id_rsa
<type password>
Run Code Online (Sandbox Code Playgroud)

这真的很烦人。

我注意到在输出ssh-agentSSH_AGENT_PID环境变量每次都是不同的。我的预感是这个环境变量SSH_AUTH_SOCK是不需要在单个 shell 会话中重新添加密钥的原因。当我调用该ssh程序时,它将使用这些环境变量与 进行通信ssh-agent并且身份验证将成功。

我想知道是否有一种ssh-agent在会话之间共享s的方法。也许正确的做法是在开始前就加我的SSH密钥tmux和配置tmux以保护SSH_AUTH_SOCKSSH_AGENT_PID环境变量。我真的不确定。解决这个问题的标准方法是什么?

tmux ssh-agent

12
推荐指数
2
解决办法
3198
查看次数

即使命令无效,bash也在进程替换中等待进程

我正在尝试errpipe使用stderr通过过滤器运行的简单 api编写实用程序脚本。起初我尝试使用 bash 的进程替换功能来实现它。

#!/bin/bash

com="$1"
errpipe="$2"

$com 2> >(1>&2 $errpipe)
Run Code Online (Sandbox Code Playgroud)

这样做的问题是当com不存在时输出看起来很奇怪。

如果我输入

sh-3.2$ ./errpipe foo cat
Run Code Online (Sandbox Code Playgroud)

我得到

sh-3.2$ ./errpipe foo cat
sh-3.2$ ./errpipe: line 6: foo: command not found
@
Run Code Online (Sandbox Code Playgroud)

@代表光标。换句话说,shell 提示打印得太早了。我怀疑这是因为主 shell 脚本没有等待进程替换过程完成。在wait脚本末尾添加a似乎并不能解决问题。

我打开一个解决方案,使用bashkshzsh或可能有些疯狂的awk功能。我想我知道如何使用 C 或 Perl 之类的东西将它们连接在一起,这些东西公开了更丰富的 API 来操作进程和文件描述符,但我想避免使用它,除非没有替代方案。


一种“几乎有效”的解决方案是使用在$$shell fork 时没有改变的事实,并在 errpipe 完成时向父级发出信号。

#!/bin/bash

com="$1"
errpipe="$2"

$com 2> >(1>&2 $errpipe; kill -SIGUSR1 $$)

while true; do …
Run Code Online (Sandbox Code Playgroud)

bash process-substitution

10
推荐指数
1
解决办法
2750
查看次数

curl 将 http 代码写入 stderr 或文件

我正在编写一些脚本来测试 API。我对 JSON 响应以及请求的 HTTP 状态代码感兴趣。我绝对想漂亮地打印 JSON 响应,以便于阅读。

我正在curl用来执行请求并想python -m json.tool用来漂亮地打印 json 结果。

Curl 有一个不错的选项-w,可用于显示有关请求的信息,例如%{http_code}. 不幸的是,该信息会打印到标准输出并混淆python -m json.tool. 似乎无法将其配置为忽略尾随的非 json 数据。

当我做

curl \
'--silent' \
'--insecure' \
'-L' \
'-w' \
'\n%{http_code}\n' \
'--user' \
<REDACTED> \
'-X' \
'GET' \
'--' \
'https://somecompany.com/some_api_endpoint' \
| python -m json.tool
Run Code Online (Sandbox Code Playgroud)

我得到

$ bash call_api_endpoint_script.sh 
Extra data: line 2 column 1 - line 3 column 1 (char 203 - 207) …
Run Code Online (Sandbox Code Playgroud)

curl

7
推荐指数
2
解决办法
3004
查看次数

能够将 `\r` 视为空白字符的 Shell

作为一个个人项目,我正在尝试编写一个脚本来清理在 Cygwin 下运行的 Windows 10 附带的一些无关文件。我希望脚本能够复制和粘贴,这需要它对不同类型的换行符具有健壮性。是否有任何类似shshell 可以将处理\r为空格的能力,可能是在设置了某些选项时?

这是一件奇怪的事情。答案可能归结为“是的,这是一件奇怪的事情,没有办法做到”。

cygwin newlines

7
推荐指数
1
解决办法
699
查看次数

查找特定进程的子进程数

我有一个 Python 脚本,它会生成一些子进程,但不会超过n一次。

我想编写一个 shell 脚本来确认它n在任何给定时间只有子n进程,而且通常它有进程正在运行。

如果我在 shell 脚本中有 Python 程序的 PID,我该如何检查该 PID 当前拥有的子进程数?例如

python script.py &
pid=$!
while true
do
    # do something that prints number of subprocesses of
    # the process $pid to stdout
    sleep 1
done
Run Code Online (Sandbox Code Playgroud)

bash process

6
推荐指数
1
解决办法
7459
查看次数

可移植地为动态命名的 shell 变量赋值

Slackware 14.2 上的 Almquist shell,但不是 Debian 的 Almquist shell,支持以下构造。其他类似伯恩的炮弹没有。

setvar "$varname" <...>
Run Code Online (Sandbox Code Playgroud)

Bash 显然具有动态创建变量名的能力

declare "magic_variable_$1=$(ls | tail -1)"
Run Code Online (Sandbox Code Playgroud)

我认为对可以出现的字符有一些限制$1......(=想到)。

建议将此作为在 4.0 之前的 Bashes 中伪造关联数组的解决方法。

我可以想出一个愚蠢的函数,使用eval.

注意:不要以任何理由使用此功能,这是完全不安全的。

assign_dynamically() {
    eval "$1='$2'"
}
Run Code Online (Sandbox Code Playgroud)

但是,如果该值$2包含'但不支持 中的空格或元字符$1,则这件事会令人窒息,因此它不是解决方案。

是否有一种可移植/POSIX 兼容的方法来编写一个函数,该函数分配给$2一个名为变量的变量,$1而不管任一字符串的内容如何?

shell

6
推荐指数
1
解决办法
1736
查看次数

grep -v:如何仅排除匹配的前(或最后)N 行?

有时在其他表格数据中会有一些非常烦人的行,例如

column name | other column name
-------------------------------
Run Code Online (Sandbox Code Playgroud)

我通常更喜欢通过grep -ving 一个合理唯一的字符串来删除不应该存在的垃圾行,但这种方法的问题是,如果合理唯一的字符串意外出现在数据中,那将是一个严重的问题。

有没有办法限制grep -v可以删除的行数(比如 1)?对于加分,有没有办法从末尾计算行数而不诉诸于<some command> | tac | grep -v <some stuff> | tac

grep text-processing

6
推荐指数
2
解决办法
7195
查看次数

匹配成功后停止处理 awk 中的单行?

有没有办法在 awk 中停止处理单行?是否有类似breakcontinue适用于模式-动作对而不是动作中的控制结构的东西?

假设我有以下input.txt文件,并且我试图用x0, x1, x2,替换每个名称...。但是,我想留下以空格或-单独开头的行。

-- data
bob     4
joe     5
bob     6
joe     7
Run Code Online (Sandbox Code Playgroud)

变成:

-- data
x0 4
x1 5
x0 6
x1 7
Run Code Online (Sandbox Code Playgroud)

我有以下脚本可以做到这一点。(作为旁注,使用 heredoc 而不是大量字符串文字可能有更好的结构化方法)。

#!/bin/sh
awk '
    BEGIN { c = 0; }

    # do not process lines beginning with - or space
    /^[- ]/ {
        print;
    }

    # update 
    /^[^- ]/ {
        if (! ($1 in name) ) { …
Run Code Online (Sandbox Code Playgroud)

awk

6
推荐指数
1
解决办法
4428
查看次数

Bash while 循环使用 IFS 从以冒号分隔的路径列表中读取

我正在尝试编写一个 bash 函数,其行为类似于where.bashrc 中的内置函数tcsh。在tcsh, 中where列出所有内置函数、别名和PATH具有给定名称的可执行文件的绝对路径,即使它们被隐藏,例如

tcsh> where tcsh
/usr/bin/tcsh
/bin/tcsh
Run Code Online (Sandbox Code Playgroud)

作为其中的一部分,我想遍历 中的所有内容$PATH并查看是否存在具有适当名称的可执行文件。

以下 bash 代码段旨在遍历以冒号分隔的路径列表并打印每个组件后跟一个换行符,但是,它似乎只是$PATH在一行上打印了所有内容的全部内容

#!/bin/bash
while IFS=':' read -r line; do
    printf "%s\n" "$line"
done <<< "$PATH"
Run Code Online (Sandbox Code Playgroud)

正如现在站立,bash where并且./where只是打印/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

那么,如何设置我的 while 循环,以便循环变量的值依次是冒号分隔的路径列表的每个段?

shell bash string

5
推荐指数
1
解决办法
1万
查看次数