Renaming and Moving Files in Bash or Perl?

As per OP, this can be Perl, not just bash. Here we go.

As per OP, this can be Perl, not just bash. Here we go NEW SOLUTION: (paying attention to extension) ~/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 OLD SOLUTION: (not paying attention to extension) ~/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.

This is great (I don't care about perl or bash), but I should apply the new name by preserving the extension (obtaining something like foo_1. Txt for foo. Txt, instead of foo.text.1).

I'm trying to understand how to do this... – Katie Mar 30 '10 at 22:13 @Katie - See the updates – DVK Mar 30 '10 at 22:47 @Katie - and good attitude about "don't care as long as it gets the job done" :) – DVK Mar 30 '10 at 22:48 @Katie - replace "copy()" call at the end with "move()" to move instead of copy – DVK Mar 30 '10 at 22:51 Don't know what to say. It seems to be just perfect. Thank you so much.

– Katie Mar 30 '10 at 22:55.

If you don't mind renaming the files that already exist, GNU mv has the --backup option: mv --backup=numbered * /some/other/dir.

Actually, I need to preserve the names of the files of the target dir. Plus, I should preserve the extensions. But thanks for this hint, it could be useful in other situations... – Katie Mar 30 '10 at 21:51.

Here is a Bash script: source="/some/dir" dest="/another/dir" find "$source" -maxdepth 1 -type f -printf "%f\n" | 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 The suffix is added blindly. If you have files named like "foo.

New" in both directories then the result will be one file named "foo. New" and the second named "foo.new. New" which might look silly, but is correct in that it doesn't overwrite the file.

However, if the destination already contains "foo.new. New" (and "foo. New" is in both source and destination), then "foo.new.

New" will be overwritten). You can change the if above to a loop in order to deal with that situation. This version also preserves extensions: source="/some/dir" dest="/another/dir" find "$source" -maxdepth 1 -type f -printf "%f\n" | 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.

Dennis - nice touch re: commenting out 'mv' :) – DVK Mar 30 '10 at 22:50.

I feel bad for posting this without testing it. However it is late and I have work in the morning. My attempt would look something like this: ## 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 Overall the strategy is to get each name from the source path, break it into parts, and, for any collision, iterate over names of the form "base~XX. Extension" until we find one that doesn't collide.

Obviously I have prepended the mv command with an echo because I'm a coward. Remove that at your own (files') peril.

If you don't need incremental suffix, rsync can do the job: rsync --archive --backup --suffix=. Sic src/ dst Update: find/sed/sort is used to manage versioned backup files: #! /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.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions