我尝试编写一个递归遍历目录的shell脚本,然后在每个文件中将所有大写字母转换为小写字母。要清楚,我并没有尝试更改文件名,而是更改文件中的文本。
注意事项:
最好的方法是什么?
答案 0 :(得分:5)
要将文件从小写转换为大写,您可以使用ex
(ed
的好朋友,标准编辑器):
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)
对于带有嵌入冒号或换行符的文件名,这将失败,但应该适用于其他文件,包括带空格的文件名。