make_path does not set mode as specified - perl

When I call make_path (from the core File::Path module, supplying a mode, the directory that is created does not have the mode I requested:
$ perl -MFile::Path=make_path -e 'make_path("foobar", { mode=>0770 });'
$ ls -ld foobar/
drwxr-x--- 2 itk itkadm 4096 Sep 19 11:10 foobar/
I was expecting to see:
drwxrwx--- 2 itk itkadm 4096 Sep 19 11:07 foobar/

Rather than setting the permissions for the directory to 0. Try instead just using the chmod option to File::Path::make_path
perl -MFile::Path=make_path -e 'make_path("foobar", { chmod=>0770 });'

I missed this detail in the make_path documentation:
mode: The numeric permissions mode to apply to each created directory
(defaults to 0777), to be modified by the current umask.
I was not expecting this because the shell equivalent (mkdir -m 0770 -p foobar) does not consider umask.
This works as expected:
$ perl -MFile::Path=make_path -e 'umask(0); make_path("foobar", { mode=>0770 });'
$ ls -ld foobar/
drwxrwx--- 2 itk itkadm 4096 Sep 19 11:13 foobar/
Note the umask(0).
As pointed out by Evan Carroll, the version of File::Path supplued with newer perl versions (>=5.24) have a chmod option which may be a more convenient way to set the mode of created directories.

Related

MobaXterm Busybox strange setup

I am using MobaXterm portable.
I found a strange setup, summarized here.
External commands in /bin work fine. E.g., with /bin/ssh.exe I can ssh ok.
Internal commands are
"redirected" to busybox, as
$ which cat
/bin/cat
$ ll /bin/cat
lrwxrwxrwx 1 USER001 UsersGrp 16 Jul 24 07:42 /bin/cat -> /bin/busybox.exe
at the same time aliased to files that apparently do not exist.
$ type cat
cat is aliased to `/bin/cat.exe'
These aliases apparently take precedence over files in PATH, so the commands do not work.
$ cat myfile
bash: /bin/cat.exe: No such file or directory
If I unalias, cat does not look for /bin/cat.exe but for /bin/busybox.exe, and everything is "back to normal".
$ unalias cat
$ cat myfile
Hello world
...
How can I get normal behaviour (either without aliases or with the presence of the alias targets)?
I mean not to write my own unaliases in .bashrc, this shouldn´t be needed.
Moreover, perhaps I would be breaking something.
Why would MobaXterm setup things like this?
PS: In the initial state, even ls does not work, for the same reason.
But ll works, since
$ type ll
ll is aliased to `_bbf ls -l'
$ type _bbf
_bbf is a function
...
How can I get normal behaviour?
Workarounds:
unaliasing by hand, so /bin/busybox.exe is actually used.
Below I add a script for that.
Copying .exe files from the temporary root dir when it is available, so the external versions are used.
Why would MobaXterm setup things like this?
When not using a Persistent root (/) directory, this is obtained
$ which cat
/bin/cat
$ ll /bin/cat
-rwxr-xr-x 1 RY16205 UsersGrp 49703 jul. 28 07:12 /bin/cat
$ type cat
cat is aliased to `/bin/cat.exe'
$ ll /bin/cat.exe
-rwxr-xr-x 1 USER001 UsersGrp 49703 jul. 28 07:12 /bin/cat.exe
$ cat myfile
Hello world
...
$ unalias cat
$ type cat
cat is hashed (/bin/cat)
$ cat myfile
Hello world
...
So any of the two cats work (internal busybox and external versions; I do not know if they are exactly the same).
This is because /bin points to C:\Users\user001\AppData\Local\Temp\Mxt108\bin and cat.exe is there.
But when using a Persistent root (/) directory, /bin points to <Persistent root (/) directory\bin, and cat.exe is not created there.
The former temporary root dir is removed as soon as MXT is closed.
So this is probably a configuration error from MobaXterm.
If so, the only option seems a workaround, as above.
Script for unaliasing:
#!/bin/bash
export ROOTDIR_WIN=$(cygpath -wl /)
if [[ ${ROOTDIR_WIN##*\\} == "Mxt108" ]] ; then
# Not using a Persistent root dir. Do not need to unalias.
echo "Not using a Persistent root dir. Do not need to unalias."
else
# Using a Persistent root dir. Need to unalias.
exe_linux_list="bash busybox chmod cygstart cygtermd cygwin-console-helper dircolors dwm_w32 echo grep ls MoTTY ssh ssh-pageant test twm_w32 wc xkbcomp_w32 XWin_MobaX"
for exe_linux in ${exe_linux_list} ; do
if [[ $(type -t ${exe_linux}) == "alias" ]] ; then
#type ${exe_linux}
unalias ${exe_linux}
fi
done
fi
On my MobaXterm system, /etc/profile sources /etc/baseprofile which includes aliases for all of these sorts of things, i.e.
alias "cat"="_bbf cat"
and checking that from my command prompt yields what I would expect:
$ type cat
cat is aliased to `_bbf cat'
Have you changed your system somehow so that /etc/baseprofile is not being sourced? Or have you changed /etc/baseprofile?
It also appears that you've installed the regular GNU Coreutils package, as I don't have a /bin/cat.exe.
$ ll /bin/cat.exe
ls: /bin/cat.exe: No such file or directory
Perhaps that's where your problem started but the _bbf function is supposed to handle that. Which again leads me to the belief that you've changed /etc/baseprofile somehow.
At most time, it is cool. This error maybe caused by wrong path match of cat.exe.
As for me, when I run git log, the same error message comes out. It is due to PATH variable. There are two dirs and both of them contain git.exe. One of them is half-done with a small size. And Mobaxterm choose it. :D
I confirm this by run which git and it will give the actual path out.
I fix it by
alias git='/drives/C/Program\ Files/Git/mingw64/bin/git.exe'
The following is my dirs.
├─cmd
│ git-gui.exe
│ git-lfs.exe
│ git.exe # oops
│ gitk.exe
│ start-ssh-agent.cmd
│ start-ssh-pageant.cmd
├─mingw64
│ ├─bin
│ │ git-upload-pack.exe
│ │ git.exe # the right one

something wrong when I exec a script with perl (ubuntu10.10)

I got a perl script named test_perl.pl and try to exec it.
The first line of the scrpit is:
#!/usr/bin/perl
When I try to exec this script, I get an error.
$ type perl
perl is /usr/bin/perl
$ ll /usr/bin/perl test_perl.pl
-rwxr-xr-x 2 root root 10352 2011-04-23 03:32 /usr/bin/perl*
-rwxr-xr-x 1 jim jim 12121 2013-11-21 11:47 test_perl.pl*
$ test_perl.pl
test_perl.pl: line 1: #!/usr/bin/perl: No such file or directory
I don't no why this happens.
You have a BOM (see http://en.wikipedia.org/wiki/Byte_order_mark) at the beginning of your file.
try
xxd test_perl.pl
to see it. Getting rid of the BOM will fix your script: Lots of ways to do this: Using awk to remove the Byte-order mark

Need to remove files with spaces in Debian

I need to find and remove files with spaces in them in a certain folder.
$ ls -l
total 16
-rw-r--r-- 1 smw staff 10 Feb 6 16:10 Foo Bar
-rw-r--r-- 1 smw staff 11 Feb 6 16:10 foobar
$ ls -l *\ *
-rw-r--r-- 1 smw staff 10 Feb 6 16:10 Foo Bar
$ rm -i *\ *
remove Foo Bar? y
$ ls -l
total 16
-rw-r--r-- 1 smw staff 11 Feb 6 16:10 foobar
You'll have to deal with bash's niceties when dealing with spaces...
First, you need to iterate over the files, in a way that gives you the files properly regardless of spaces. Check out this question. I'd favor this:
find ... | while read line ; do command "$line" ; done
And then it's a matter of using something like sed to change $line into whatever you need (such as the same thing without spaces) right where command "$line" is.
This is how I removed a file with a space
pi#raspberrypi ~/Music $ ls -l
-rw-r--r-- 1 pi pi 0 Feb 25 16:05 Sleep Away.mp3
pi#raspberrypi ~/Music $ rm Sleep\ Away.mp3
use the "\" forward slash to escape any spaces

How to delete a NULL file from Solaris Unix?

I have a NULL file in a directory:
-rw-r--r-- 1 blah1 blah2 83532 Nov 5 09:34 <can't see, but null here>
How do I remove this? This is very annoying as it interferes with svn status.
Thanks for any help.
Delete interactively, saying no to all of the non-null files.
/bin/rm -i *
You can remove using the iNode value (using the -i option on ls command)
# ls -li
total 16
30475938 -rw-r--r-- 1 root root 7 mar 19 10:29 -h
# find . -inum 30475938 -print
./-h
# find . -inum 30475938 -exec rm {} \;
# ls -li
total 0
In my blog, you have some examples -in Spanish- how to remove files with reserved characters.
http://sparcki.blogspot.com.es/2010/03/como-eliminar-archivos-utilizando-su.html
Urko,

What is the best way to extract a version string from a file?

I want to use a file to store the current version number for a piece of customer software which can be used by a start-up script to run the binary in the correct directory.
For Example, if the run directory looks like this:
.
..
1.2.1
1.2.2
1.3.0
run.sh
current_version
And current_version contains:
1.2.2
I want run.sh to descend into 1.2.2 and run the program foo.
The current solution is this:
#!/bin/sh
version = `cat current_version`
cd $version
./foo
It works but is not very robust. It does not check for file existence, cannot cope with multiple lines, leading spaces, commented lines, blank files, etc.
What is the most survivable way to do this with either a shell or perl script?
That's a common approach. You can check for dir/file existence using test operators such as "if [ -d "somedirectory" ]; then" or [ -t "somefile" ]
I use symbolic links more often, though. Then, you can just change your symbolic link to use the version you want.
For example,
$ ln -s 1.2.2 current_version
$ ls -al
total 20
drwxr-xr-x 5 dbreese dbreese 4096 2008-09-15 13:34 .
drwxr-xr-x 3 dbreese dbreese 4096 2008-09-15 13:34 ..
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.2.1
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.2.2
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.3.0
lrwxrwxrwx 1 dbreese dbreese 6 2008-09-15 13:34 current_version -> 1.2.2/
Then your script can just use "cd current_version".
I would change the script to accept an argument. The argument should be a filename. Open the file using whatever scripting language you prefer [perl, python] and traverse the file until you find a match for your version.
I would use a regex... something along the lines of /\d\.\d\.\d/ . then have it execute the application through your script.
You can check for existence using the && and || operators:
!$/bin/sh
version = `cat current_version`
cd $version && ./foo || echo "Bad version"
The && operator causes the second statement to only execute if the first one succeeds (exit status 0), and the || operator causes the second statement to execute only if the first one fails (exit status non-zero).
I'm not sure what you mean by coping with multiple lines, leading spaces, or commented lines.
If the versioning will always be in #.#.# format, you could do this:
ls | grep ^[0-9]\.[0-9]\.[0-9]$ | sort -nr | head -n 1
That will list the versions in descending numerical order, then selects the first of those
What about:
#!/usr/bin/perl -w
use strict;
use warnings;
my $version_file = 'current_version';
open my $fh, '<', $version_file or die "Can't open $version_file: $!";
# Read version from file
my $version = <$fh>;
chomp $version;
# Remove whitespace (and match version)
die "Version format not recognized" if $version !~ m/(\d+\.\d+\.\d+)/;
my $dir = $1;
die "Directory not found: $dir" unless -d $dir;
# Execute program in versioned directory.
chdir $dir;
system("./foo");
!#/bin/sh
if [ -e 'current_version' ]; then
version=`cat current_version`;
version=`echo $version | tr -ds [[:blank:]]`
if [ -n "$version" ]; then
if [ -d "$version" ]; then
cd "$version"
else
echo $version is not a directory
fi
else
echo version_file contained only blanks
fi
else
No file named current_version exists
fi