gem555 has asked for the wisdom of the Perl Monks concerning the following question:
The move command does'nt execute on the file below.
Is it because there is a '&' sign in between?
How to solve the problem if '&' exists in filename.
#!/usr/bin/perl
$filename = 'new&name.txt';
`mv $filename new&filename_renamed.txt`;
On execution gives out the message as below
sh: name.txt: command not found
sh: filename_renamed.txt: command not found
mv: missing file argument
Try `mv --help' for more information.
[2] Done(127) name.txt new
Re: move command
by Corion (Patriarch) on Jul 08, 2009 at 06:42 UTC
|
Don't start an external program when Perl has a fine built-in that has no problems with special characters - see rename:
use strict;
my $filename = 'new&name.txt';
rename $filename => "new&filename_renamed.txt";
| [reply] [d/l] |
|
rename has limitations -- in particular, on most systems it will only work if the source and destination are on the same filesystem. File::Copy::move will use rename if it's appropriate, or do a copy-and-delete if rename won't work, so it's a more flexible solution.
| [reply] [d/l] [select] |
Re: move command
by moritz (Cardinal) on Jul 08, 2009 at 06:54 UTC
|
Using backticks in void context isn't very useful - capturing an output to discard it might not be the best option.
As Corion wrote, perl has the rename builtin, with the caveat that it doesn't work across file system boundaries.
A possible solution is to use the list form of system, which doesn't pass the arguments to a shell, thus not having a problem with shell meta characters:
system('mv', $filename, 'new&filename_renamed.txt') == 0
or die "Can't move files: $?";
| [reply] [d/l] |
Re: move command
by hobbs (Monk) on Jul 08, 2009 at 06:45 UTC
|
You're creating problems by invoking the shell -- so stop invoking the shell. The sensible solution to this specific problem is to use File::Copy's move method to move the file instead of shelling out to mv.
The solution to the general problem of running external commands without the shell getting in your way is to use the LIST forms of system and open instead of using single-arg system, single-arg open, or backticks. But that's just for future reference, because you don't need an external command to rename/move a file. | [reply] [d/l] [select] |
Re: move command
by jbt (Chaplain) on Jul 08, 2009 at 04:56 UTC
|
Yes, that is causing the problem. Do you want to rename the file without an ampersand?
#!/usr/bin/perl
$filename = 'new\&name.txt';
`mv $filename new_filename_renamed.txt`;
| [reply] [d/l] |
Re: move command
by rovf (Priest) on Jul 08, 2009 at 08:00 UTC
|
In addition to what has been said already, I would like to point out that using an ampersand as a character in a filename (or a space, exclamation mark, \0, @ and similar
special characters), while technically not forbidden, should
be avoided. This is just begging for trouble sooner
or later. Restrict yourself to [-A-Za-z0-9_.+%] when writing
filenames, and you will be fine.
On second thought, maybe you should also drop [A-Z] from the
list, in case your application needs to run on Windows as
well...
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] [select] |
|
Actually under all Unix filesystems I'm aware off, \0 is one of two characters that is forbidden in a filename. The other is the slash off course.
Having said that, I fully agree with the advice to restrict the characters. Typically, I only use ASCII letters, digits, underscores, dashes and dots.
| [reply] |
|
"+" and "-" should be avoided as the lead character. % is the var sigil used by the Windows shell (e.g. echo %PATH%, echo %1, etc). On second thought, maybe you should also drop
in case your application needs to run on Windows as well...
huh? Windows has no problems with lowercase letters, digits, underscores, and fewer problems than unix with the dash.
| [reply] [d/l] [select] |
|
Windows has no problems with lowercase letters
Unfortunately it does. Try to create a file "FOO.TXT", and then create a new file "foo.txt". You will find that the second file "replaces" the first one. The reason is that Windows internally does not distinguish between lower and upper case. Well, this applies to Windows until XP. I don't know whether this has been fixed in Vista.
and fewer problems than unix with the dash
Partially true. Strictly speaking, Unix has no problem with dash, but you likely mean that the vast majority of Unix command line tools use the dash to denote switches, while the majority of Windows command line tools use a slash to denote a switch. Since there are still quite a few Windows utilities which also use a hyphen to denote a command line switch, you should avoid on Windows files starting with either a hyphen or a slash, while on Unix you will have a happier life if you don't have files starting with a hyphen, and a slash is ruled out as valid character anyway.
Underscores, AFIK, are no problems in either OS. In Windows, there are some characters which you should avoid, since they have special meaning to the shell: caret (^), percent (%), double quotes ("), parentheses. Caret and percent are fine on Unix, but the others are better avoided there too. While Unix itself is tolerant on most characters, many of the shells on Unix have their own special characters, such as a tilde (~) on the starting position, or a $ sign.
On Unix, I try to avoid characters which are special to the most common shells (bash, zsh, tcsh), not because it would be strictly necessary, but because it makes life easier. Given that at least tcsh is available on Windows as well - though it seems to be much less in use than on Unix -, I avoid these characters on Windows too.
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] |
|
|
|
|
|