是否可以使用 bash 大括号扩展删除而不是将子字符串添加到文件名中?
考虑以下场景,可以使用以下技术为文件名添加后缀:
mv offlineimap.conf{,.minimal}
Run Code Online (Sandbox Code Playgroud)
它所做的是重命名offlineimap.conf,offlineimap.conf.minimal这非常方便,尤其是。用于制作备份文件(例如 swith.bak扩展名)。
但是也可以从给定的文件名中减去子字符串,如下所示:
mv offlineimap.conf.minimal{,-minimal}
Run Code Online (Sandbox Code Playgroud)
这里我用-一个假设的特殊字符来减去子串。
我希望第二种技术能够从现有文件的名称中offlineimap.conf删除.minimal后缀。
我需要在我的 macOS 终端中执行以下 shell 脚本。循环永远不会执行超过其第一次迭代的次数。
function execute_function() {
# Launch job
number_of_jobs=$1
echo "Launching ${number_of_jobs} jobs"
for i in {1..$1}; do
job_id=`head /dev/urandom | tr -dc A-Z0-9 | head -c 6 ; echo ''`
echo "Launching Job: $job_id"
echo $i
done
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我总是得到:
execute_function 10
Launching 10 jobs
Launching Job: XX9BWC
{1..10}
Run Code Online (Sandbox Code Playgroud)
如果我替换:$1与$number_of_jobs或"${number_of_jobs}"
我在 Bash 正则表达式中遇到了以下不对称示例,这让我感到困惑。我想知道我在做什么是非标准的并导致这种行为,否则我所缺少的这种行为背后的逻辑是什么。
假设我有一个名为文件列表的目录file1.txt来file20.txt。我想在我最喜欢的文本编辑器中打开所有这些。为此,从某种意义上说,Bash 必须“读取”目录的内容并将它们传递给 Vim。我可以使用以下正则表达式来做到这一点:
vim file{[1-9],1[0-9],20}.txt
Run Code Online (Sandbox Code Playgroud)
这有效。执行此命令后,Vim会打开,并在缓冲区列表里,我可以看到所有的文件file1.txt来file20.txt。
现在假设我们处于不同的场景:我们从一个空目录开始,我们想要将文件创建file1.txt到file20.txt. 为此,从某种意义上说,Bash 必须将文件名“写入”到目录中。不幸的是,在这种情况下,前面的命令不起作用。我没有创建所需的 20 个文件,而是在缓冲区列表中得到以下文件:
file[1-9].txt
file[0-9].txt
file20.txt
Run Code Online (Sandbox Code Playgroud)
因此[],与其将方括号解释为正则表达式的一部分,不如将它们合并到名称中。
为什么在阅读与写作时会发生这种不对称,我将来如何避免这种情况?
例如,我想将一些文件名放在大括号内进行扩展,如下所示:
$ ls
blue_texture blue_waves green_light
$ ls -m | tr -d ' \n'
blue_texture,blue_waves,green_light
$ echo foo/bar/{`ls -m | tr -d ' \n'`}
foo/bar/{blue_texture,blue_waves,green_light}
Run Code Online (Sandbox Code Playgroud)
我的问题为什么大括号扩展在这里不起作用?我希望它按以下方式工作:
$ echo foo/bar/{blue_texture,blue_waves,green_light}
foo/bar/blue_texture foo/bar/blue_waves foo/bar/green_light
Run Code Online (Sandbox Code Playgroud) IINM 我的系统在ing时出现故障bash
for i in {0..10000000}; # Seven zeroes.
do
false;
done # `bash` exited and its `tmux` pane/window was closed.
Run Code Online (Sandbox Code Playgroud)
或者
for i in $(seq 0 10000000); # Seven zeroes.
do
false;
done # `bash` exited and its `tmux` pane/window was closed.
Run Code Online (Sandbox Code Playgroud)
但不是什么时候
for i in {0..1000000}; # Six zeroes.
do
false;
done # Finished correctly.
Run Code Online (Sandbox Code Playgroud)
您能否简要解释一下此行为的内部原理并提示完成任务的解决方法?
对于基准测试,我运行了以下命令:
for i in {1..100000000}; do
echo "$i" line >> file
done
Run Code Online (Sandbox Code Playgroud)
Bash扩展了大括号并将列表存储1 2 3 4 5 6 ... 100000000在内存中。
我认为这会以某种方式解除分配。毕竟,它是一个临时变量。几天过去了,该bash进程仍然占用 17.9GB 的内存。
我可以强制 bash 清除这些临时变量吗?我不能使用unset,因为我不知道变量名。(显然unset i没有帮助)
当然,一种解决方法是关闭外壳并打开一个新的外壳。
我还在 bash 邮件列表中询问了这个问题,并得到了Chet Ramsey的有用回复:
那不是内存泄漏。Malloc 实现不需要将内存释放回内核;bash malloc(和其他人)只在有限的情况下这样做。使用 mmap 或 sbrk 从内核获取并由 malloc 实现保存在缓存中的内存不构成泄漏。泄漏是应用程序或 malloc 本身不再有句柄的内存。
malloc() 基本上是应用程序和内核之间的缓存。它可以决定何时以及如何将内存返还给内核。
我正在尝试在 bash 中创建一个拼字游戏助手,当给定一个字符列表时,它会找到/usr/share/dict/words文件中的所有单词。
例如,当给定字母时a,c,r,t
单词cart将匹配
单词car也将匹配
单词carat将不匹配
但是,如果a,a,c,r,t给出
Thencarat将匹配。
我试图找出是否可以只使用grep,我怀疑大括号扩展
{a,c,r,t}{a,c,r,t}可能对生成所有可能的字母组合有用,但相反,我遇到了类似的错误
grep: aaac: No such file or directory
grep: aaar: No such file or directory
grep: aaat: No such file or directory
Run Code Online (Sandbox Code Playgroud)
运行命令时
$ grep {a,c,r,t}{a,c,r,t}{a,c,r,t}{a,c,r,t} /usr/share/dict/words
当我使用像"{a,c,r,t}{a,c,r,t}"or 之类的引号时"\{a,c,r,t\}\{a,c,r,t\}",大括号扩展根本不起作用
我知道上面的命令不应该作为拼字游戏的助手,但错误仍然出乎意料。命令有什么问题,我该如何解决?另外,可以grep用某种方式来制作拼字游戏助手吗?
在bash我可以使用花括号来模式匹配多个文件,例如
ls *.{dot,svg,err}
Run Code Online (Sandbox Code Playgroud)
如果没有特定扩展名的文件,我会收到警告,但会列出其余文件。
ls: 无法访问 '*.err': 没有那个文件或目录
但是,在zsh我得到一个错误并且没有为现有文件产生输出。
zsh:未找到匹配项:*.err
这也适用于删除,在尝试删除文件时:
rm -f *.{dot,svg,err}
Run Code Online (Sandbox Code Playgroud)
将在bash没有任何错误或警告的情况下删除所有匹配的文件,但zsh它会出错并且根本不会删除任何内容。
有没有办法使zsh行为与 相同bash,或者是否有另一种方法可以轻松删除/列出现有文件¹?
¹显然我可以做类似的事情,find . -name '*.dot' -or -name '*.svg' -or -name '.err' | xargs rm但这并不是特别容易/实用。
概括:
我正在尝试设置一个 systemd 计时器来使用该rsync命令定期备份目录。我创建了一个rsync在终端中手动运行时有效的命令,但在作为 systemd 计时器运行时它无法正常工作。
详细解释:
作为一个简单的例子,我有以下目录树/home/trevor/test_dir/:
dir_a/
file_a.png
dir_b/
file_b.png
dir_c/
file_c.png
Run Code Online (Sandbox Code Playgroud)
我想用来rsync将此目录复制到我的 SSD 中进行备份(安装在/my_ssd/)。但我想排除目录dir_a和dir_b. 所以我运行命令
dir_a/
file_a.png
dir_b/
file_b.png
dir_c/
file_c.png
Run Code Online (Sandbox Code Playgroud)
当我从终端运行该命令时,该命令有效:它排除目录dir_a和dir_b,但保留dir_c.
接下来,我尝试创建一个 systemd 服务和计时器来定期运行该命令(请注意,我主要从Arch Linux Wiki 上的systemd/Timers 页面确定了以下步骤)。我制作以下服务文件
/etc/systemd/system/backup_test.service:
rsync -a --exclude={/dir_a,/dir_b} /home/trevor/test_dir/ /my_ssd/test_dir/
Run Code Online (Sandbox Code Playgroud)
以及以下计时器文件,该文件将每 30 秒运行一次命令(例如)
/etc/systemd/system/backup_test.timer:
[Unit]
Description=systemd backup test
[Service]
Type=simple
ExecStart=rsync -a --exclude={/dir_a,/dir_b} /home/trevor/test_dir/ /my_ssd/test_dir/
Run Code Online (Sandbox Code Playgroud)
我使用 启动计时器systemctl …
我正在寻找最简单的解决方案,将其$*作为输入,并扩展到以给定字符串为前缀和后缀的每个元素:
$*=foo bar baz
<solution(x,y)>=xfooy xbary xbazy
Run Code Online (Sandbox Code Playgroud)
我可以进行前置或附加,但不能同时进行:
echo ${*/#/x}
# prints xfoo xbar xbaz
Run Code Online (Sandbox Code Playgroud)
echo ${*/%/y}
# prints fooy bary bazy
Run Code Online (Sandbox Code Playgroud)
我无法结合这两种解决方案。该文档声称在 parameter=* 情况下扩展返回的值是一个列表,但我无法这样使用它。我想将生成的值数组作为单独的参数传递给另一个命令,因此简单地构建单个字符串是行不通的。