微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在Bash或Perl中重命名和移动文件

嗨,我完全是新的Bash和StackOverflow。

我需要将一组文件(全部包含在同一文件夹中)移动到目标文件夹,在该文件夹中可能已经存在具有相同名称文件

在存在特定文件的情况下,我需要在移动它之前重命名文件,例如在文件名后添加一个增量整数。

应该保留扩展名(换句话说,附加的增量整数应该扩展名之前 )。 文件名可以包含中间的点。

正则expression式来replace每行中最后一次出现的string

自动更新的文本输出到屏幕和文件

使用awk将文件拆分成多个文件,但采用date格式

如果文件存在并且不是空的。 总是给我虚假的价值

查找并重命名没有扩展名的文件

最初,我想比较两个文件夹有一个现有的文件列表(我做了这个“通信”),但后来我有点卡住了。 我想我只是想以最复杂的方式来做事情。

任何暗示在“bash的方式”做到这一点? 如果是在bash脚本以外的脚本中完成的话。

如何在Windows批处理脚本中将%USERNAME%的值转换为小写?

输出bash脚本的格式

如何安装.pm来运行perl脚本

如果行以另一个string开始,则replace文件中的string

在sh中初始化数组

根据OP,这可以是Perl,而不仅仅是bash。 开始了

解决方案:(注意扩展)

~/junk/a1$ ls f1.txt f2.txt f3.txt z1 z2 ~/junk/a1$ ls ../a2 f1.txt f2.1.txt f2.2.txt f2.3.txt f2.txt z1 # I split the one-liner into multiple lines for readability $ perl5.8 -e '{use strict; use warnings; use File::copy; use File::Basename; my @files = glob("*"); # assume current directory foreach my $file (@files) { my $file_base2 = basename($file); my ($file_base,$ext) = ($file_base2 =~ /(.+?)([.][^.]+$)?$/); my $new_file_base = "../a2/$file_base"; my $new_file = $new_file_base . $ext; my $counter = 1; while (-e $new_file) { $new_file = "$new_file_base." . $counter++ . $ext; } copy($file,$new_file) || die "Could not copy $file to $new_file: $!n"; } }' ~/junk/a1> ls ../a2 f1.1.txt f1.txt f2.1.txt f2.2.txt f2.3.txt f2.4.txt f2.txt f3.txt z1 z1.1 z2

解决方案:(不注意扩展)

~/junk/a1$ ls f1 f2 f3 ~/junk/a1$ ls ../a2 f1 f2 f2.1 f2.2 f2.3 # I split the one-liner into multiple lines for readability $ perl5.8 -e '{use strict; use warnings; use File::copy; use File::Basename; my @files = glob("*"); # assume current directory foreach my $file (@files) { my $file_base = basename($file); my $new_file_base = "../a2/$file_base"; my $new_file = $new_file_base; my $counter = 1; while (-e $new_file) { $new_file = "$new_file_base." . $counter++; } copy($file,$new_file) || die "Could not copy $file to $new_file: $!n"; } }' ~/junk/a1> ls ../a2 f1 f1.1 f2 f2.1 f2.2 f2.3 f2.4 f3

如果你不介意重命名已经存在的文件,GNU mv有--backup选项:

mv --backup=numbered * /some/other/dir

这是一个Bash脚本:

source="/some/dir" dest="/another/dir" find "$source" -maxdepth 1 -type f -printf "%fn" | while read -r file do suffix= if [[ -a "$dest/$file" ]] then suffix=".new" fi # to make active,comment out the next line and uncomment the line below it echo 'mv' ""$source/$file"" ""$dest/$file$suffix"" # mv "source/$file" "$dest/$file$suffix" done

后缀是盲目添加的。 如果在两个目录中都有名为“foo.new”的文件,那么结果将是一个名为“foo.new”的文件,而另一个名为“foo.new.new”的文件可能看起来很愚蠢,但它是正确的覆盖文件。 但是,如果目的地已经包含“foo.new.new”(并且“foo.new”在源和目的地中),则“foo.new.new”将被覆盖)。

你可以把上面的if改成一个循环来处理这种情况。 此版本还保留了扩展名

source="/some/dir" dest="/another/dir" find "$source" -maxdepth 1 -type f -printf "%fn" | while read -r file do suffix= count= ext= base="${file%.*}" if [[ $file =~ . ]] then ext=".${file##*.}" fi while [[ -a "$dest/$base$suffix$count$ext" ]] do (( count+=1 )) suffix="." done # to make active,comment out the next line and uncomment the line below it echo 'mv' ""$source/$file"" ""$dest/$file$suffix$count$ext"" # mv "$source/$file" "$dest/$file$suffix$count$ext" done

我感觉不好,没有测试它发布。 不过,已经很晚了,我早上上班了。 我的尝试看起来像这样:

## copy files from src to dst ## inserting ~XX into any name between base and extension ## where a name collision would occur src="$1" dst="$2" case "$dst" in /*) :;; # absolute dest is fine *) dst=$(pwd)/$dst;; # relative needs to be fixed up esac cd "$src" find . -type f | while read x; do x=${x#./} # trim off the ./ t=$x; # initial target d=$(dirname $x); # relative directory b=$(basename $x); # initial basename ext=${b%%.*}; # extension b=${b##*.}; # basename with ext. stripped off let zz=0; # initial numeric while [ -e "$dst/$t" ]; do # target exists,so try constructing a new target name t="$d/$bb~$zz.$ext" let zz+=1; done echo mv "./$x" "$dst/$t" done

总体而言,策略是从源路径中获取每个名称,将其分解成若干部分,并且对于任何碰撞,迭代形式为“base〜XX.extension”的名称,直到找到一个不相互冲突的名称

很明显,我已经把mv命令加上了前缀,因为我是个懦夫。 删除自己的(文件)危险。

如果你不需要增量后缀,rsync可以完成这项工作:

rsync --archive --backup --suffix=.sic src/ dst

更新

find / sed / sort用于管理版本化的备份文件

#!/bin/bash src="${1}" dst="${2}" if test ! -d "${src}" -o ! -d "${dst}" ;then echo Usage: $0 SRC_DIR DST_DIR >&2 exit 1 fi rsync --archive --backup "${src}/" "${dst}/" new_name() { local dst=$1 local prefix=$2 local suffix=$3 local max=$(find ${dst} -type f -regex ".*${prefix}.[0-9]*.${suffix}$" | sed 's/.*.([0-9]*)..*/1/'|sort -n|tail -n 1) let max++ echo ${prefix}.${max}.${suffix} } # swap BACKUP-extension/real-extension for backup_file in $(find $dst -name "*~"); do file=${backup_file%~} prefix=${file%.*} suffix=${file##*.} suffix=${suffix%~} mv ${backup_file} $(new_name $dst $prefix $suffix) done

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐