Bash脚本以递归方式使文件中的所有文本都为小写

时间:2012-11-27 21:25:21

标签: bash

我尝试编写一个递归遍历目录的shell脚本,然后在每个文件中将所有大写字母转换为小写字母。要清楚,我并没有尝试更改文件名,而是更改文件中的文本。

注意事项:

  1. 这是一个旧的Fortran项目,我试图让它更易于访问
  2. 我不想创建新文件,而是使用更改
  3. 覆盖旧文件
  4. 此目录中有多个不同的文件扩展名,包括.par .f .txt和其他
  5. 最好的方法是什么?

5 个答案:

答案 0 :(得分:5)

要将文件从小写转换为大写,您可以使用exed的好朋友,标准编辑器):

ex -s file <<EOF
%s/[[:upper:]]\+/\L&/g
wq
EOF

或者,如果你喜欢一行中的东西:

ex -s file <<< $'%s/[[:upper:]]\+/\L&/g\nwq'

结合find,您可以执行以下操作:

find . -type f -exec bash -c "ex -s -- \"\$0\" <<< $'%s/[[:upper:]]\+/\L&/g\nwq'" {} \;

对于文件名中的空格和有趣符号,此方法是100%安全的。没有创建,复制或移动辅助文件;文件只能编辑。

编辑。

使用glenn jackmann的建议,您也可以写:

find . -type f -exec bash -c 'printf "%s\n" "%s/[[:upper:]]\+/\L&/g" "wq" | ex -- -s "$0"' {} \;

(专业人士认为它可以避免尴尬的逃脱;这是因为它更长)。

答案 1 :(得分:2)

您可以使用tr命令将所有大写字符(A-Z)转换为小写(a-z) 并指定一系列字符,如:

$ tr 'A-Z' 'a-z' <be.fore >af.ter

tr中还有一些特殊语法用于指定大小写的这种范围 转化:

$ tr '[:upper:]' '[:lower:]' <be.fore >af.ter

tr实用程序复制给定输入以生成输出,并替换或删除所选字符。 tr缩写为翻译或音译。它将两组字符作为参数,并将 first set 中字符的出现替换为来自其他 set 的相应元素,即它用于翻译字符。 / p>

tr "set1" "set2" < input.txt > output.txt

虽然tr不支持正则表达式,但是它确实支持一系列字符。

确保两个参数最终都有相同数量的字符。 如果第二个参数较短,则会重复其最后一个字符以匹配 第一个参数的长度。如果第一个参数更短,则第二个参数将是 被截断以匹配第一个的长度。

答案 2 :(得分:2)

sed -e 's/\(.*\)/\L\1/g' *

或者你可以从find

中输入文件

答案 3 :(得分:1)

扩展@ nullrevolution的解决方案:

find /path_to_files -type f -exec sed --in-place -e 's/\(.*\)/\L\1/g' '{}' \;

这一个班轮将查找以/ path_to_files开头的所有子目录中的所有文件作为基本目录。

警告:这将更改* / path_to_file *下 EVERY 目录中所有文件的大小写,因此请确保您要执行此操作在执行此脚本之前。您可以使用以下命令限制基于文件扩展名的查找范围:

find /path_to_files -type f -name \*.txt -exec sed --in-place -e 's/\(.*\)/\L\1/g' '{}' \;

您可能还想在修改原始文件之前备份原始文件:

find / path_to_files -type f -name * .txt -exec sed --in-place = -orig -e's /(。*)/ \ L \ 1 / g''{}'\;

这将保留原始文件名,同时制作未修改的副本,并在文件名后附加“_orig”(即 file.txt 将成为 file.txt-orig )。

每件作品的解释:

find /path_to_file这会将基目录设置为提供的路径。

-type f这将仅在目录层次结构中搜索文件。

-exec COMMAND '{}' \;这为每个匹配的文件执行一次提供的命令。 '{}'将替换为当前文件名。 \;表示命令的结束。

sed --in-place -e 's/\(.*\)/\L\1/g' --in-place将在不备份文件的情况下将文件发送到文件中。正则表达式使用反向引用\1来引用整行,并使用\L转换为小写。

<强>可选

(对于更古老的解决方案。)

find /path_to_files -type f -exec dd if='{}' of='{}'-lc conv=lcase \;

答案 4 :(得分:0)

在Unix类环境中识别文本文件可能有点棘手。你可以这样做:

set -e -o noclobber
while read f; do
   tr 'A-Z' 'a-z' <"$f" >"f.$$"
   mv "$f.$$" "$f"
done < <(find "$start_directory" -type f -exec file {} + | cut -d: -f1)

对于带有嵌入冒号或换行符的文件名,这将失败,但应该适用于其他文件,包括带空格的文件名。