小编Kon*_*lph的帖子

将 `rm` 移至垃圾箱

是否有一个 Linux 脚本/应用程序,而不是删除文件,而是将它们移动到一个特殊的“垃圾”位置?我想用它来代替rm(甚至可能是后者的别名;这样做有利有弊)。

“垃圾”是指一个特殊的文件夹。单个mv $* ~/.trash是第一步,但理想情况下,这还应该处理多个同名文件的垃圾处理,而不会覆盖旧的垃圾文件,并允许使用简单的命令(一种“撤消”)将文件恢复到其原始位置。此外,如果在重新启动时自动清空垃圾(或防止无休止增长的类似机制),那就太好了。

存在针对此问题的部分解决方案,但“恢复”操作尤其重要。是否有任何现有的解决方案不依赖图形外壳中的垃圾系统?

(顺便说一句,这种方法是否合理,而不是使用频繁的备份和 VCS 是否合理,一直存在无休止的讨论。虽然这些讨论有一定的意义,但我相信我的要求仍然存在。)

shell rm

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

如何实现水平猫?

标准cat逐行连接文件(逐行,如果你愿意的话)。我发现自己最近越来越需要水平 cat命令;即一个命令,它接受一个文件列表并将它们水平连接起来,逐列。到目前为止,我已经使用了临时解决方法,但我想知道是否存在一个很好的解决方案。

为了澄清,请考虑以下两个文件之间cathcat的比较:

$ cat a.dat 1.dat
a b
c d
1 2
3 4
$ hcat -s ' ' a.dat 1.dat
a b 1 2
c d 3 4
Run Code Online (Sandbox Code Playgroud)

(与cat我们需要指定分隔符不同,因为按照惯例,UNIX 文件的末尾没有列分隔符。)

scripting text-processing files cat

27
推荐指数
1
解决办法
7487
查看次数

有状态的 bash 函数

我想在 Bash 中实现一个函数,它在每次调用时增加(并返回)一个计数。不幸的是,这似乎很重要,因为我在子 shell 中调用该函数,因此它无法修改其父 shell 的变量。

这是我的尝试:

PS_COUNT=0

ps_count_inc() {
    let PS_COUNT=PS_COUNT+1
    echo $PS_COUNT
}

ps_count_reset() {
    let PS_COUNT=0
}
Run Code Online (Sandbox Code Playgroud)

这将按如下方式使用(因此我需要从子shell调用函数):

PS1='$(ps_count_reset)> '
PS2='$(ps_count_inc)   '
Run Code Online (Sandbox Code Playgroud)

这样,我就会有一个带编号的多行提示:

> echo 'this
1   is
2   a
3   test'
Run Code Online (Sandbox Code Playgroud)

可爱的。但由于上述限制不起作用。

一个无效的解决方案是将计数写入文件而不是变量。但是,这会在多个同时运行的会话之间产生冲突。当然,我可以将 shell 的进程 ID 附加到文件名。但我希望有一个更好的解决方案,不会让我的系统因大量文件而混乱。

bash prompt shell-script function subshell

17
推荐指数
2
解决办法
1798
查看次数

为什么我不能在块中的地址之后对 sed 命令进行分组?

我正在尝试使用sed打印所有行,直到但不包括特定模式。我不明白为什么以下不起作用:

sed '/PATTERN/{d;q}' file
Run Code Online (Sandbox Code Playgroud)

根据我对 sed 脚本的理解,这个表达式应该会导致以下情况:

  • 当一行匹配时/PATTERN/,执行由命令组成的组
    1. d删除模式空间(=当前行)
    2. q打印当前模式空间后的 uit

孤立地,既/PATTERN/d/PATTERN/q工作;也就是说,d删除有问题的行,并q导致sed终止,但在打印行之后,如文档所述。但是将这两个操作组合在一个块中似乎会导致q被忽略。

我知道我可以使用Q而不是{d;q}作为 GNU 扩展(这按预期工作!)但我有兴趣了解为什么上述不起作用,以及我以何种方式误解了文档。


我的实际用例(只是稍微)更复杂,因为文件的第一行实际上与模式匹配,我跳过它(在做了一些替换之后):

sed -e '1{s/>21/>chr21/; n}' -e '/>/{d;q}' in.fasta >out.fasta
Run Code Online (Sandbox Code Playgroud)

但是上面的简化案例表现出相同的行为。

sed

11
推荐指数
2
解决办法
661
查看次数

完全按原样将参数传递给函数

我有以下功能:

bar() { echo $1:$2; }
Run Code Online (Sandbox Code Playgroud)

我正在从另一个函数调用这个函数,foo. foo本身被称为如下:

foo "This is" a test
Run Code Online (Sandbox Code Playgroud)

我想获得以下输出:

This is:a
Run Code Online (Sandbox Code Playgroud)

也就是说,bar接收到的参数应该与我传入的标记相同foo

foo需要如何实施才能实现这一目标?我尝试了以下两种实现,但都不起作用:

  • foo() { bar $*; }

    - 输出: this:is

  • foo() { bar "$*"; }

    - 输出: this is a test:

我的问题是如何有效地保留参数的引用。这可能吗?

bash quoting function arguments

10
推荐指数
2
解决办法
2万
查看次数

使用 coreutils 换行和缩进文本

精简版

我想创建一个多行文本的表格显示,类似于以下内容:

all       Build all targets
document  Create documentation of source files in the subfolders
          `src` and `script`, and write it to `man`
test      Run unit tests
Run Code Online (Sandbox Code Playgroud)

目前,我对此的输入如下所示,但这当然可以更改:

all---Build all targets
document---Create documentation of source files in the subfolders `src` and `script`, and write it to `man`
test---Run unit tests
Run Code Online (Sandbox Code Playgroud)

我已经尝试通过awkwrap/的组合来实现这一点,pr但是虽然换行有效,但缩进却没有。这是我目前的方法:

…
| awk -F '---' "{ printf '%-10s %s\n', $1, $2 }" \
| fold -w $(($COLUMNS - 1)) -s
Run Code Online (Sandbox Code Playgroud)

它生成输出

all       Build …
Run Code Online (Sandbox Code Playgroud)

make coreutils text-processing text-formatting fold

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

将粘贴与行主输入一起使用

我可以通过paste如下方式从单列输入创建一个包含多列的文件:

some_command | paste - -
Run Code Online (Sandbox Code Playgroud)

some_command在以列主要格式生成数据时有效。换句话说,输入

1
2
3
4
Run Code Online (Sandbox Code Playgroud)

结果在输出

1   2
3   4
Run Code Online (Sandbox Code Playgroud)

但是,我想要相反的,即我想要

1   3
2   4
Run Code Online (Sandbox Code Playgroud)

背景:我想将M 个文件中的所有第N列收集到一个聚合文件中。我尝试通过以下方式执行此操作:

cut -f 5 "${files[@]}" | paste - - - - - …
Run Code Online (Sandbox Code Playgroud)

(与M -秒)。但如前所述,这不起作用,正如paste预期的列主要输入。我不禁认为应该有一个 coreutils(或纯 Bash)解决方案。

shell-script text-processing paste

4
推荐指数
1
解决办法
183
查看次数

正确引用通过另一个命令间接传递的数组

我需要将文件名数组传递给命令,并保留正确的引用。到目前为止,一切都很好。不幸的是,该命令实际上是一个子命令,又被另一个命令调用。具体来说,命令是:

\n\n
git filter-branch --index-filter \\\n    \'git rm -rf --cached \xe2\x80\xb9file1\xe2\x80\xba \xe2\x80\xb9file2\xe2\x80\xba\xe2\x80\xa6\' \\\n    HEAD\n
Run Code Online (Sandbox Code Playgroud)\n\n

为简单起见,我\xe2\x80\x99m 将在下面用一个显示相同问题的更简单的命令替换它:

\n\n
printf \'%s\\n\' \'cmd file1 file2\xe2\x80\xa6\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我\xe2\x80\x99已经得到了一个数组files=(\'a b\' c)。我想要的结果是上面的命令在一行中打印,并cmd根据需要单独引用后面的每个标记(例如,当存在\xe2\x80\x99s 空格时)。

\n\n

如果我手动扩展并引用文件名,它会起作用:

\n\n
$ printf \'%s\\n\' \'cmd \'\\\'\'a b\'\\\'\' c\'\n\xe2\x86\x92 cmd \'a b\' c\n
Run Code Online (Sandbox Code Playgroud)\n\n

(或者,我可以混合使用单引号和双引号来达到相同的结果。)

\n\n

但如果我尝试传递数组,它就不再起作用:

\n\n
    \n
  1. $ (set -x; printf \'%s\\n\' "cmd \'${files[@]}\'")\n+ printf \'%s\\n\' \'cmd \'\\\'\'a b\' \'c\'\\\'\'\'\n\xe2\x86\x92 cmd \'a b\nc\'\n
    Run Code Online (Sandbox Code Playgroud)
  2. \n
  3. $ (set -x; printf \'%s\\n\' \'cmd \'\\\'"${files[@]}"\\\')\n+ printf \'%s\\n\' …
    Run Code Online (Sandbox Code Playgroud)

bash array quoting arguments

4
推荐指数
1
解决办法
3175
查看次数

在 while 循环中写入错误流

我有大约以下代码:

cat infile | while read line; do
    echo 2> 'log ' $line
    echo $line
done > outfile
Run Code Online (Sandbox Code Playgroud)

outfile已正确创建。但是,STDERR 输出刚刚消失:它既没有显示在终端上,也没有显示在outfile. 如果我用done > outfile 2> errfilethen替换上面的最后一行,则errfile创建,但为空。

我可以从循环内捕获错误输出吗,最好是通过将其直接流式传输到父 STDERR 中(以上是较大脚本的一部分,其标准错误流由另一个进程捕获)?

bash io-redirection

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