可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is there a shortcut in Shell/Bash that can rename all the files in a folder based on a regex or some other criteria. What I am looking for here is in my folder documents, that has let's say a 100 text files with the following naming convention:
<longdocumentidentifier>-doc-<counter>.txt.
I need to rename all the files with the above given convention to just:
doc-<counter>.txt
Is there a one-liner that can help me with the above?
回答1:
I would suggest something like this:
for i in *-doc-*.txt; do mv $i ${i/*-doc-/doc-}; done
${i/*-doc-/doc-}
replaces the first occurrence of *-doc-
with doc-
.
If you need to do more than one replacement (see comment number 1), you need to use the ${var//Pattern/Replacement}
variant. If you need to replace the beginning of the name you need to use ${var/#Pattern/Replacement}
, if you need to replace the end (ie: the extension) you need to use the ${var/%Pattern/Replacement}
form.
See http://tldp.org/LDP/abs/html/parameter-substitution.html#EXPREPL1 for more details
回答2:
If you have rename
then, rename 's/^.*-doc-/doc-/' *.txt
should do the trick.
回答3:
There is prename
, that allows you to use REGEX:
prename 's/^.*-doc-(.*\.txt)$/doc-$1/' *.txt
Use the option -n
to simulate:
prename -n 's/^.*-doc-(.*\.txt)$/doc-$1/' *.txt
Note: This is the shipped as rename
in many Linux distributions, but not in all of them -- so I'm using the canonical name for the utility that comes with Perl.
回答4:
The rename command built in to most linux, eg, will do this easily.
Personally, I prefer regexps too which is why I've been carrying around this script for a very very very long time (read: since the late 80s or early 90s):
#!/usr/bin/perl
($op = shift) || die "Usage: $0 expr [files]]\n";
if(!@ARGV)
{
@ARGV = <STDIN>;
chop(@ARGV);
}
for (@ARGV)
{
$was = $_;
eval $op;
die $@ if $@;
if ($was ne $_)
{
print "rename($was,$_)\n";
rename($was,$_);
}
}
Which, when installed lets you do things like this:
script-name 's/.*-doc(.*).txt/doc$1.txt/' *.txt
回答5:
If you want to recurse into sub-directories, there is also:
find . -maxdepth N -type f -name "$pattern" | sed -e 'p' -E -e "s/$str1/$str2/g" | xargs -n2 mv
On system that automatically support extended Regexps, you can leave away the -E
.
Advantages:
- recurses into sub-directories
- you can control the maxdepth of the recursion
- you can rename files and/or directories (-type f|d)
Disadvantages:
- slightly more complicated regexps, because you have to strip out the path to get at the file name
(answer amended from here)
回答6:
mmv "*-doc-*" "doc-#2"
mmv command stands for "mass move"
回答7:
If you don't mind external tool, then here's one: rnm (web page)
For your particular problem the command would be:
rnm -rs '/.*-doc-/doc-/' *.txt
Or
rnm -rs '/.*-(doc-.*\.txt)/\1/' *.txt
You can find more examples/docs here.
回答8:
find . -name '*scss' | xargs -L1 -I {} echo {} {} | sed 's/css.scss$/scss/' | xargs -L1 mv
for example if you have a bunch of files ending with ".css.scss" and you want to rename them to end with simply ".scss" (ie remove the .css part)
tweak the regexp and find arguments to your needs