5

我想用 awk/sed/bash 将小写文件名更改为大写

您的帮助将不胜感激

aaaa.txt
vvjv.txt
acfg.txt

期望的输出

AAAA.txt
VVJV.txt
ACFG.txt
4

10 回答 10

18

前言:

如果您不关心扩展的大小写,只需在 shell 循环中使用 'tr' 实用程序:

for i in *.txt; do mv "$i" "$(echo "$i" | tr '[a-z]' '[A-Z]')"; done

如果您确实关心扩展的情况,那么您应该知道有不止一种方法可以做到这一点(TIMTOWTDI)。就个人而言,我相信这里列出的Perl解决方案可能是 Linux 下最简单、最灵活的解决方案。如果您有多个文件扩展名,只需指定您希望保持不变的数字。BASH4解决方案也是一个很好的解决方案,但您必须愿意将扩展名写出几次,或者使用另一个变量来存储它。但是,如果您需要严重的可移植性,那么我建议使用八进制的这个答案中的最后一个解决方案。某些版本的 Linux 还附带了一个名为rename的工具这也可能值得一试。它的用法因发行版而异,因此请键入man rename以获取更多信息。

解决方案:

使用Perl

# single extension
perl -e 's/\.[^\.]*$/rename $_, uc($`) . $&/e for @ARGV' *.txt

# multiple extensions
perl -e 's/(?:\.[^\.]*){2}$/rename $_, uc($`) . $&/e for @ARGV' *.tar.gz

使用BASH4

# single extension
for i in *.txt; do j="${i%.txt}"; mv "$i" "${j^^}.txt"; done

# multiple extensions
for i in *.tar.gz; do j="${i%.tar.gz}"; mv "$i" "${j^^}.tar.gz"; done

# using a var to store the extension:
e='.tar.gz'; for i in *${e}; do j="${i%${e}}"; mv "$i" "${j^^}${e}"; done

使用GNU awk

for i in *.txt; do

    mv "$i" $(echo "$i" | awk '{ sub(/.txt$/,""); print toupper($0) ".txt" }');
done

使用GNU sed

for i in *.txt; do

    mv "$i" $(echo "$i" | sed -r -e 's/.*/\U&/' -e 's/\.TXT$/\u.txt/');
done

使用BASH3.2

for i in *.txt; do

    stem="${i%.txt}";

    for ((j=0; j<"${#stem}"; j++)); do

        chr="${stem:$j:1}"

        if [[ "$chr" == [a-z] ]]; then

            chr=$(printf "%o" "'$chr")

            chr=$((chr - 40))

            chr=$(printf '\'"$chr")
        fi

        out+="$chr"
    done

    mv "$i" "$out.txt"

    out=
done
于 2012-09-17T23:01:58.800 回答
9

通常,对于小写/大写修改,经常使用“tr”(翻译字符)实用程序,它来自用于字符替换的命令行实用程序集。

dtpwmbp:~ pwadas$ echo "xxx" | tr '[a-z]' '[A-Z]'
XXX
dtpwmbp:~ pwadas$ 

此外,对于重命名文件,还有 perl ( man rename ) 提供的“rename”实用程序。

    SYNOPSIS
       rename [ -v ] [ -n ] [ -f ] perlexpr [ files ]

DESCRIPTION
       "rename" renames the filenames supplied according to the rule specified as the first argument.  The perlexpr argument is a Perl expression which is expected to modify the $_ string in
   Perl for at least some of the filenames specified.  If a given filename is not modified by the expression, it will not be renamed.  If no filenames are given on the command line,
   filenames will be read via standard input.

   For example, to rename all files matching "*.bak" to strip the extension, you might say

           rename 's/\.bak$//' *.bak

   To translate uppercase names to lower, you'd use

           rename 'y/A-Z/a-z/' *
于 2012-09-17T23:09:08.290 回答
5

我建议使用rename,如果您只想大写文件名而不是扩展名,请使用以下内容:

rename -n 's/^([^.]*)\.(.*)$/\U$1\E.$2/' *

\U大写所有直到\E,请参阅perlreref(1)-n当您对输出感到满意时删除。

于 2012-09-18T08:16:39.097 回答
1
for f in *.txt; do
  mv "$f" "`tr [:lower:] [:upper:] <<< "${f%.*}"`.txt"
done
于 2012-09-17T23:13:24.697 回答
1

Bash 4 参数扩展可以执行大小写更改:

for i in *.txt; do
  i="${i%.txt}"
  mv "$i.txt" "${i^^?}.txt"
done
于 2012-09-18T00:26:13.290 回答
1

重击:

for f in *.txt; do 
    no_ext=${f%.txt}
    mv "$f" "${no_ext^^}.txt"
done
于 2012-09-18T00:29:28.273 回答
1

一种更简单、轻量级和便携的方法是:

for i in *.txt
do 
    fname=$(echo $i | cut -d"." -f1 | tr [a-z] [A-Z])
    ext=$(echo $i | cut -d"." -f2)
    mv $i $fname.$ext
done

这几乎适用于 BASH 的每个版本,因为我们使用的是每个 Unix 风格中最常见的外部实用程序(cut、tr)。

于 2012-09-18T12:26:11.170 回答
1

只需使用(在终端上):

for i in *.txt; do mv $i `echo ${i%.*} | tr [:lower:] [:upper:]`.txt; done;
于 2013-06-13T07:10:57.743 回答
0

这可能对您有用(GNU sed):

printf "%s\n" *.txt | sed 'h;s/[^.]*/\U&/;H;g;s/\(.*\)\n/mv -v \1 /' | sh

或更简单地说:

printf "%s\n" *.txt | sed 'h;s/[^.]*/\U&/;H;g;s/\(.*\)\n/mv -v \1 /e'
于 2012-09-18T07:04:10.410 回答
0
for i in *.jar; do mv $i `echo ${i%} | tr [:upper:] [:lower:]`; done;  

这对我有用。

于 2017-12-28T11:06:14.407 回答