Python中递归控制台工具的最佳实践

时间:2010-09-05 15:42:58

标签: python command-line

命令行工具的最佳实践(接口和实现)是什么? 处理目录树中的选定文件?

我举一个想到的例子,但我正在寻找'最佳实践':

flipcase foo.txt foo2.txt

可以处理foo.txt并将结果保存为foo2.txt。

flipcase -rv *.txt

可以处理当前目录中的所有文本文件 -r--recursive将包含所有子目录 -v会在处理时向stdout打印一些信息。

我在这个例子中看到的一个问题是,*.txt参数是 有时由shell(Unix和Vista)扩展,所以我无法应用这种模式 走路子目录时。
我想原因是,在Unix上,这些工具与find的调用相结合, 但这似乎并不常见于Windows。它也使得打印难以打印 最后总结。

要求:

  • 必须在Unix,Windows XP,Windows 7和Mac上运行
  • 应该遵循这些平台上的常见约定。 (是的,我知道。但我正在寻找合理的妥协方案。 例如,在Windows上使用-而不是/即可。)
  • 不应该依赖单独的find命令,比如grep。
  • 必须适用于目录中的单个文件,文件模式和模式 的层次结构。
  • 应该使用标准的Python库构建,例如: OptionParseros.walk
  • 可以处理多种模式,例如*.txt,*.html

有关设计决策的其他问题:

  • 此工具应返回什么(状态代码)?
  • 这个工具应该处理哪些ctrl键,以什么方式处理?
  • 是否应该支持stdin而不是单个文件?可配置或 自动检测?
  • 是否应支持输出重定向?可配置还是自动检测? 在这种情况下如何处理调试输出?
  • 模式应该是glob语法还是正则表达式?
  • 是否有支持递归的通用模式语法? 也许recursive:*.txt 在这种情况下,-r选项不是必需的。
  • 创建已修改文件的备份的最佳做法是什么? 选项-b,或者更确切地说是备份,并添加--no-backup选项
  • 对于单个文件,应该可以指定目标文件名。怎么样?
  • 应打印哪些状态信息,然后热配置? 它应该是默认的冗长,我们允许-q安静吗? 或者总是打印一点,并允许-v(或-vv)提升此值或-q为 完全闭嘴?

我真的不希望得到一个正确答案,但可能是少数 对优秀样本项目的想法和指示。

4 个答案:

答案 0 :(得分:2)

根据我的经验,最好的出发点是构建一个遵循基本Unix原则的工具 - 即从标准输入读取并写入标准输出。这允许人们以灵活的方式使用您的工具:

flipcase input.txt > output.txt
othercommand | flipcase > output.txt
flipcase | othercommand > ouput.txt
flipcase input1.txt  input2.txt > output.txt

下一个功能可能是就地编辑:

# Modify input files directly.
flipcase -i input.txt

# Create backup copies before modifying originals.
flipcase -i --backup-suffix '_BAK' input.txt
flipcase -i --backup-prefix 'BAK_' input.txt

# Regex for power users.
flipcase -i --backup-regex 's/foo/bar/' input.txt

在详细模式下,该工具不应写入标准输出,因为这会与上述核心原则冲突。它应该写入标准错误或用户定义的日志文件。

flipcase -v         input.txt > output.txt
flipcase -v log.txt input.txt > output.txt

之后,添加递归行为。这里的方向不太明确,但我会抛出一些想法。在典型的递归情况下,程序的参数可能是目录,用户需要提供其他选项来定义各种类型的过滤行为(即要处理的文件类型)。

flipcase -r -i --backup-suffix '_BAK' --filter-glob '*.txt' dir1 dir2
flipcase -r -i --backup-suffix '_BAK' --filter-glob '*.txt' --filter-glob 'log*.dat' dir
flipcase -r -i --backup-suffix '_BAK' --filter-regex 'log\w+\.(txt|log)$' dir1 dir2

# Don't do in-place editing. Instead create new files within the structure.
flipcase -r --newname-suffix '_NEW'              --filter-glob '*.txt' dir1 dir2
flipcase -r --newname-regex 's/\.txt$/_new.txt/' --filter-glob '*.txt' dir1 dir2

# Create the backups or the new files in a parallel directory
# structure rather than within the original structure.
flipcase -r -i --backup-tree 'backup_dir'   --filter-glob '*.txt' dir1 dir2
flipcase -r -i --new-tree    'newfiles_dir' --filter-glob '*.txt' dir1 dir2

答案 1 :(得分:1)

  

最佳做法是什么(界面   和实现)命令行   处理所选文件的工具   目录树?

在实现命令行工具时,我认为没有单一的标准或“最佳实践”。虽然,通过查看和试验像GNU coreutils这样的精心构建的工具,您将获得许多见解。

另外,我认为你也在寻找类似的东西:http://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html

阅读和试验Unix的方法实际上解决了许多关于设计决策的问题。

  

我看到这个问题   例如,* .txt参数是   有时由shell扩展(Unix   和Vista),所以我不能应用这个   走路子目录时的模式。

在Unix中,*会自动展开。我不确定Windows,但如果我没有弄错,*没有扩展,所以你可以简单地使用glob.glob(sys.argv[1])。 Unix的解决方法是逃避通配符,但必须有更好的方法。

答案 2 :(得分:1)

要解决问题的全局部分,列表中的奇怪人物确实支持Windows。 UNIX方式,也是一种好方法,让shell处理globbing。你只需要一个文件列表。我知道没有UNIX工具它自己的globbing(在这样的基本情况下)。我建议你自己也不要这样做,但要依靠shell。

在Windows上,您可以引用人们使用带有Cygwin的shell,或类似的东西。当然,Windows用户通常会避开命令行,所以如果你构建一个GUI,他们也会很开心。

这不包括您的-r转换。但那里很难。您是否希望向用户提供指定“具有扩展名.txt的子目录中的所有文件”的能力?请注意,像ZSH这样的现代shell可以执行递归到目录的globs,例如:

rm **/*.tmp

并且,正如您所说,您始终可以使用find。因此,这里的推荐确实需要考虑您工具的细节。 rsync可以实现自己的-r转换,但假设的flipcase可能不会。

答案 3 :(得分:0)

递归处理通常使用os.path.walk完成,但您可以创建自己的版本以使用Python生成器,它更加命令行友好:管道将在处理时获得输出。这是a tested and documented proof of concept

使用Python 3,您不必这样做,因为它提供了创建生成器的os.walk

然后,按照FM建议使用optparse创建CLI界面。