|
Home > Archive > Unix administration > May 2005 > Autocreate Directory with a new name
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Autocreate Directory with a new name
|
|
| binary-nomad@hotmail.com 2005-05-24, 6:04 pm |
| How do I create a directory, and if it fails, if a directory with that
name already exists there, retry with a different name?
I'm a bit confused with how to handle the error resulting from the
"Mkdir" failing, and put that inside the loop, so it knows it failed,
and then retries.
Is a while loop the best thing to use in this case?
Thanks very much 
The Nomad.
| |
| Dave Hinz 2005-05-24, 6:04 pm |
| On 24 May 2005 10:56:43 -0700, binary-nomad@hotmail.com <binary-nomad@hotmail.com> wrote:
> How do I create a directory, and if it fails, if a directory with that
> name already exists there, retry with a different name?
You could count the ones with similar names - do a
ls /path/to/dir | grep name | wc -l
to see how many directories with 'name' as part of their name exist
in /path/to/dir. Add one to that, (or make the first one without
a number) and mkdir with whatever name and the number that wc gave
you.
> I'm a bit confused with how to handle the error resulting from the
> "Mkdir" failing, and put that inside the loop, so it knows it failed,
> and then retries.
Or, you could make them with a time/date stamp, down to the second if
that's fast enough to not have 2 during the same second...or serialize
during a second if it's more than 1 a second.
> Is a while loop the best thing to use in this case?
Nope. Direct measurement is always preferable to trial and error.
The real question might be "what are you trying to do that you feel
this is necessary".
Dave Hinz
| |
| matt_left_coast 2005-05-24, 6:04 pm |
| binary-nomad@hotmail.com wrote:
> How do I create a directory, and if it fails, if a directory with that
> name already exists there, retry with a different name?
>
> I'm a bit confused with how to handle the error resulting from the
> "Mkdir" failing, and put that inside the loop, so it knows it failed,
> and then retries.
>
> Is a while loop the best thing to use in this case?
>
>
>
> Thanks very much 
>
>
>
> The Nomad.
You could use a loop. Set a variable like
TRUE=false
set up a while loop that will run until TRUE == TRUE
When you determain that the directory has been successfully written, change
TRUE to TRUE and it will exit the loop.
Each loop would increase the counter by one. But I would not try to write
the file first. I would want to test if the file was there first using
something like the -f option. Something like
if [ ! -f /path/to/file/<file_name>.$counter ] ; then
note: so I don't get flamed over file names with spaces, something I don't
use, I'll leave it to you to figure out how to format the statement if you
do use filenames with spaces.
Of course there are different reasons for not writing the file. You would
not want to try file names forever so you would need to check if the actual
write was successful. I would suggest you check the return code ${?} to see
if it failed or not. If you have written your script right and the return
code shows that the write has failed, it is probably for a reason that
trying with a different name would not solve and you should exit the script
with an error message. If the return code indicates the write was
successful, then set TRUE to TRUE.
| |
| matt_left_coast 2005-05-24, 6:04 pm |
| Dave Hinz wrote:
> On 24 May 2005 10:56:43 -0700, binary-nomad@hotmail.com
> <binary-nomad@hotmail.com> wrote:
>
> You could count the ones with similar names - do a
> ls /path/to/dir | grep name | wc -l
> to see how many directories with 'name' as part of their name exist
> in /path/to/dir. Add one to that, (or make the first one without
> a number) and mkdir with whatever name and the number that wc gave
> you.
>
Just counting the directories that are similar and adding one has a problem.
Let's say you have 3 directories:
dir_1
dir_2
dir_4
you count to see how many dir* directories you have and get 3. Add one and
try to write the dir dir4...
If you wanted to use this approach, I would suggest pulling out just the
number part of the name, doing a sort and taking the hightest number and
adding 1...
Just a thought.
>
> Or, you could make them with a time/date stamp, down to the second if
> that's fast enough to not have 2 during the same second...or serialize
> during a second if it's more than 1 a second.
This would be the way I would approach the problem depending on the
requirements of the job. I can't think of a reason why I would not find
this acceptable, but I have seen pointy haired bosses that want things done
in particular ( in the most negative connotation of "particular") ways.
>
>
> Nope. Direct measurement is always preferable to trial and error.
> The real question might be "what are you trying to do that you feel
> this is necessary".
Agreed, as long as direct mesurement gives you something reliable to get the
job done.!
>
> Dave Hinz
| |
| Chris F.A. Johnson 2005-05-24, 6:04 pm |
| On Tue, 24 May 2005 at 17:56 GMT, binary-nomad@hotmail.com wrote:
> How do I create a directory, and if it fails, if a directory with that
> name already exists there, retry with a different name?
>
> I'm a bit confused with how to handle the error resulting from the
> "Mkdir" failing, and put that inside the loop, so it knows it failed,
> and then retries.
>
> Is a while loop the best thing to use in this case?
mkdir "$DirName" 2>/dev/null || {
base=$DirName
n=1
while :
do
DirName=$base-$n
mkdir "$DirName" && break
n=$(( $n + 1 ))
done
}
This could be made somewhat faster by using a test for the
existence of the directory (or a file of the same name).
--
Chris F.A. Johnson <http://cfaj.freeshell.org>
========================================
==========================
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
| |
| Michael Heiming 2005-05-24, 6:04 pm |
| In comp.unix.shell binary-nomad@hotmail.com:
> How do I create a directory, and if it fails, if a directory with that
> name already exists there, retry with a different name?
> I'm a bit confused with how to handle the error resulting from the
> "Mkdir" failing, and put that inside the loop, so it knows it failed,
> and then retries.
> Is a while loop the best thing to use in this case?
mkdir dir_$((`ls -d dir_* | tail -1 | sed 's/dir_//'`+1))
Sounds difficult at first, but presuming there's at least "dir_1"
available, there's no need to test at all.;) Should work at least
in bash/ksh.
Good luck
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvpunry@urvzvat.qr | PERL -pe 'y/a-z/n-za-m/'
#bofh excuse 82: Yeah, yo mama dresses you funny and you need
a mouse to delete files.
| |
| Bit Twister 2005-05-24, 6:04 pm |
| On 24 May 2005 10:56:43 -0700, binary-nomad@hotmail.com wrote:
> How do I create a directory, and if it fails, if a directory with that
> name already exists there, retry with a different name?
>
> I'm a bit confused with how to handle the error resulting from the
> "Mkdir" failing,
> and put that inside the loop, so it knows it failed,
> and then retries.
Why retry, except for hardware failure, it is not going to heal it's
self unless it is remoted mounted.
> Is a while loop the best thing to use in this case?
I would. You can always test the return code $? for success 0 or
failure -ne 0.
| |
| Chris F.A. Johnson 2005-05-24, 8:48 pm |
| On Tue, 24 May 2005 at 22:23 GMT, Michael Heiming wrote:
> In comp.unix.shell binary-nomad@hotmail.com:
>
>
>
>
> mkdir dir_$((`ls -d dir_* | tail -1 | sed 's/dir_//'`+1))
>
> Sounds difficult at first, but presuming there's at least "dir_1"
> available, there's no need to test at all.;) Should work at least
> in bash/ksh.
Or, without using ls, tail and sed, in any POSIX shell:
set -- dir_[0-9]*
eval last=\${$#}
mkdir dir_$(( ${last#dir_} + 1 ))
Both of these assume that there is a file or directory called
dir_NUM, where NUM is an integer.
--
Chris F.A. Johnson <http://cfaj.freeshell.org>
========================================
==========================
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
| |
| matt_left_coast 2005-05-24, 8:48 pm |
| Michael Heiming wrote:
> In comp.unix.shell binary-nomad@hotmail.com:
>
>
>
>
> mkdir dir_$((`ls -d dir_* | tail -1 | sed 's/dir_//'`+1))
>
> Sounds difficult at first, but presuming there's at least "dir_1"
> available, there's no need to test at all.;) Should work at least
> in bash/ksh.
>
> Good luck
>
There is a little problem with this aproach. First, let's look at the
directories I have set up for the demo:
$ ls -d dir_*
dir_1/ dir_10/ dir_2/ dir_3/ dir_9/
Notice that I used the same ls format and notice the location of dir_10.
Now the tail part:
$ ls -d dir_* | tail -1
dir_9/
Are we starting to see the problem yet?
| |
| Michael Heiming 2005-05-25, 2:48 am |
| In comp.unix.shell matt_left_coast <Not@given.org>:
> Michael Heiming wrote:
[..][vbcol=seagreen]
> There is a little problem with this aproach. First, let's look at the
> directories I have set up for the demo:
[..]
> $ ls -d dir_* | tail -1
> dir_9/
> Are we starting to see the problem yet?
mkdir dir_$((`ls dir_* | awk 'NF>0'|sed 's/dir_//'| sed 's/://'| sort -rn | head -1`+1))
Not really, only your missing imagination fixing the minor problem.;)
(Left beautifying for someone else, but you should get the idea)
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvpunry@urvzvat.qr | PERL -pe 'y/a-z/n-za-m/'
#bofh excuse 334: 50% of the manual is in .pdf readme files
| |
| Michael Heiming 2005-05-25, 2:48 am |
| In comp.unix.shell Chris F.A. Johnson <cfajohnson@gmail.com>:
> On Tue, 24 May 2005 at 22:23 GMT, Michael Heiming wrote:
[vbcol=seagreen]
> Or, without using ls, tail and sed, in any POSIX shell:
> set -- dir_[0-9]*
> eval last=\${$#}
> mkdir dir_$(( ${last#dir_} + 1 ))
> Both of these assume that there is a file or directory called
> dir_NUM, where NUM is an integer.
Hi Chris!
Looks on the first view as if it would have the same problem as
"matt_left_coast" already pointed out as soon as n>=10 in
dir_[n]?
mkdir dir_$((`ls dir_* | awk 'NF>0&&/^dir_/{sub("dir_","");sub(":","");print}'| sort -rn | head -1`+1))
This seems to cure things, on the first view, could be possibly
made shorter...
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvpunry@urvzvat.qr | PERL -pe 'y/a-z/n-za-m/'
#bofh excuse 89: Electromagnetic energy loss
| |
| matt_left_coast 2005-05-25, 2:48 am |
| Michael Heiming wrote:
> In comp.unix.shell matt_left_coast <Not@given.org>:
>
> [..]
> [..]
>
>
>
> mkdir dir_$((`ls dir_* | awk 'NF>0'|sed 's/dir_//'| sed 's/://'| sort -rn
> | head -1`+1))
>
> Not really, only your missing imagination fixing the minor problem.;)
Buzz, wrong. I was the one that suggested pulling out only the number and
doing the sort before you even posted your first message ;)
> (Left beautifying for someone else, but you should get the idea)
>
| |
| Michael Heiming 2005-05-25, 2:48 am |
| In comp.unix.shell Michael Heiming <michael+USENET@www.heiming.de>:
> In comp.unix.shell Chris F.A. Johnson <cfajohnson@gmail.com>:
[vbcol=seagreen]
[vbcol=seagreen]
[vbcol=seagreen]
[vbcol=seagreen]
> Hi Chris!
> Looks on the first view as if it would have the same problem as
> "matt_left_coast" already pointed out as soon as n>=10 in
> dir_[n]?
> mkdir dir_$((`ls dir_* | awk 'NF>0&&/^dir_/{sub("dir_","");sub(":","");print}'| sort -rn | head -1`+1))
> This seems to cure things, on the first view, could be possibly
> made shorter...
In addition, I'll wait now the five minutes until Stephane
CHAZELAS shows us how easy we could do it using zsh.;)
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvpunry@urvzvat.qr | PERL -pe 'y/a-z/n-za-m/'
#bofh excuse 227: Fatal error right in front of screen
| |
| Chris F.A. Johnson 2005-05-25, 2:48 am |
| On Wed, 25 May 2005 at 06:17 GMT, Michael Heiming wrote:
> In comp.unix.shell Chris F.A. Johnson <cfajohnson@gmail.com>:
>
>
>
>
> Hi Chris!
>
> Looks on the first view as if it would have the same problem as
> "matt_left_coast" already pointed out as soon as n>=10 in
> dir_[n]?
I usually pad the number so that the above code would work.
The problem can be overcome (up to 999) by:
set -- dir_[0-9] dir_[0-9][0-9] dir_[0-9][0-9][0-9]
It can be extended if more than 999 directories will be required.
> mkdir dir_$((`ls dir_* | awk 'NF>0&&/^dir_/{sub("dir_","");sub(":","");print}'| sort -rn | head -1`+1))
>
> This seems to cure things, on the first view, could be possibly
> made shorter...
I use a loop when I need something like this:
base=$DirName
n=1
while [ -e "$DirName" ]
do
case $n in ## Add more padding if you expect more than 999 dirs.
?) zn=00$n ;;
??) zn=0$n ;;
*) zn=$n ;;
esac
DirName=$base_$zn
n=$(( $n + 1 ))
done
mkdir "$DirName"
--
Chris F.A. Johnson <http://cfaj.freeshell.org>
========================================
==========================
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
| |
| Lew Pitcher 2005-05-25, 8:53 pm |
| -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
binary-nomad@hotmail.com wrote:
> How do I create a directory, and if it fails, if a directory with that
> name already exists there, retry with a different name?
You've received quite a bit of advice and discussion on this.
I'd like to suggest a different approach.
Why not create a deliberately unique-named directory (say, with something like
tempfile(1) or mktemp(1) ), and then try to rename it to the target name?
If the rename fails, then you have the end result of your "retry with a
different name" requirement. OTOH, if the rename succeeds, then you have the
end result of your "create a directory" requirement.
- --
Lew Pitcher
Master Codewright & JOAT-in-training | GPG public key available on request
Registered Linux User #112576 (http://counter.li.org/)
Slackware - Because I know what I'm doing.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
iD8DBQFClQuwagVFX4UWr64RAkY6AJ9fcPP7nb9U
EheBW4CpUXuGg5E0egCglRHm
LmpU7sTvekpOdUXynmbUoWY=
=Y6Gs
-----END PGP SIGNATURE-----
|
|
|
|
|