对我来说,所有内置工具使用起来都有些麻烦(我的 shell 引用正确吗?它会做正确的事吗?我可以轻松预览更改吗?)。
几年前,我写了rpt,它将接受它的命令行参数,打开一个文本编辑器(让你编辑文件名),然后在旧的和新的上运行一个命令(默认mv)文件名。
最近,我更进一步,这里是fea(对于每个参数):
#!/usr/bin/env python3
# fea: For Each Argument
# https://thp.io/2019/rpt-and-fea.html
import sys, shlex, re
_, cmd, *args = sys.argv
print('\n'.join(re.sub(r'[{](.)([^}]*?)(\1)([^}]*?)(\1)[}]',
lambda m: shlex.quote(re.sub(m.group(2), m.group(4), arg)),
cmd).replace('{}', shlex.quote(arg)) for arg in args))
会发生以下替换:
{} -> insert arg
{/regex/replacement/} -> run re.sub(regex, replacement) on the arg,
you can pick any character for "/", as long
as it appears at the start, middle and end
(to separate the regex from the replacement)
一些用例:
# Create backup files
fea "cp {} {}.bak" *.py
# Encode WAV files with oggenc
fea "oggenc {} -o {/wav$/ogg/}" *.wav
# Decode MP3 files with mpg123
fea "mpg123 -w {/mp3$/wav/} {}" *.mp3
# Render markdown documents to HTML
fea "markdown {} > {/md$/html/}" *.md
# Fancy replacement
fea "markdown {} > {#input/(.*).md#output/\1.html#}" input/*.md
# As mentioned above, note that you need to pipe the
# fea output into a shell to execute the command
fea "cp {} {}.bak" *.py | sh -e -x
您的用例可以这样覆盖:
find . -name '*.in' -print0 | xargs -0 fea "python somescript.py {} {/in$/out/}"
或者如果文件只是在当前文件夹中:
fea "python somescript.py {} {/in$/out/}" *.in
或者,如果您将zsh 与recursive globbing 一起使用:
fea "python somescript.py {} {/in$/out/}" **/*.in
如果您对它显示的命令感到满意,只需将其输出通过管道传输到sh -e -x(或bash 或其他)以执行它们。
虽然可以使用 shell(或任何参数/变量扩展)创建 for 循环,但 shell 引用和转义很难正确(对我来说),fea 工具可以确保它也适用于奇怪的名字:
touch 'some$weird "filename.py'
touch 'and !! more.py'
touch 'why oh why?.py'
touch "this is ridiculous'.py"
fea "cp {} {}.bak" *.py | sh -e -x
详情请见rpt and fea blog post。