mkdir recursion with permissions - bash

It's a simple question, I'm writing a bash script called from cron grouping files in tar file and classifing into a dir structure.
These dir needs a special owner and permissions, and I call mkdir command thru su:
#!/bin/bash
... # shortened code
$PERMS=750
$DIR=/home/luser/0/01/012/0123
$OWNER=luser
... # shortened code
su -c "mkdir -m $PERMS -p $DIR" $OWNER
Output for ll -R /home/luser/0
/home/luser/0:
total 4
drwxr-xr-x 3 luser luser 4096 Jan 7 18:13 01
/home/luser/0/01:
total 4
drwxr-xr-x 3 luser luser 4096 Jan 7 18:13 012
/home/luser/0/01/012:
total 4
drwxr-x--- 2 luser luser 4096 Jan 7 18:13 0123
/home/luser/0/01/012/0123:
total 0
Only the deepest dir has permissions (750) setting rightly.
I don't know how deep it's the last directory and set permissions for all home's file it's too hard (too much files).
PS: I'm googled about that, but I find nothing.

You can restrict the permissions on the parent directories via umask. Here is an example:
PERMS=750
UMASK=$(echo "$PERMS" | tr "01234567" "76543210")
DIR=/home/luser/0/01/012/0123
OWNER=luser
su -c "umask $UMASK; mkdir -m $PERMS -p $DIR" $OWNER
In action:
> PERMS=750
> UMASK=$(echo "$PERMS" | tr "01234567" "76543210")
> (umask $UMASK; mkdir -m $PERMS -p 1/2/3/4)
> ll -R .
.:
drwxr-x--- 3 luser luser 4096 Jan 7 1:38 1/
./1:
drwxr-x--- 3 luser luser 4096 Jan 7 1:38 2/
./1/2:
drwxr-x--- 3 luser luser 4096 Jan 7 1:38 3/
./1/2/3:
drwxr-x--- 2 luser luser 4096 Jan 7 1:38 4/

Related

how can find directory

when starting the tcl script a directory is created via a bash command. at the end of my script i want to read the directory name of the latest dirs. but my script does not find the newest directory but only the 2nd newest
bind pub "-|-" !aa pub:aaa
proc pub:aaa {nick host handle channel arg} {
set home "/home/user"
set bb [exec bash -c "start.sh"]
after 3000
set latest [exec bash -c "ls -td $home/jpg/*/ | head -n1"]
putnow "PRIVMSG $channel :$latest"
}
before starting it has the following folders in the directory:
drwxr-xr-x 2 user user 4096 Jun 24 18:30 aaa
drwxr-xr-x 2 user user 4096 Jun 24 18:14 bbb
after starting it has the following folders in the directory
drwxr-xr-x 2 user user 4096 Jun 24 18:30 aaa
drwxr-xr-x 2 user user 4096 Jun 24 18:14 bbb
drwxr-xr-x 2 user user 4096 Jun 24 18:35 ccc
output is :
<#testbot> aaa
it should be so
<#testbot> ccc
he finds the directory created during which the tcl script is not running
how can I display the newest, newly created directory?
regards
Instead of trying to exec out to a shell to find the most recently modified directory, I'd do it in pure tcl:
proc latest_directory {path {time mtime}} {
set dirs {}
foreach dir [glob -nocomplain -type d $path/*] {
file stat $dir s
lappend dirs $s($time) $dir
}
if {[llength $dirs] == 0} {
error "No directories found in $path"
} else {
return [lindex [lsort -integer -decreasing -stride 2 $dirs] 1]
}
}
# Then in pub:aaa
set latest [latest_directory $home/jpg]
As for why you're not getting ccc... hard to say for sure without seeing your start.sh script, but if it ends up running stuff in the background that continues after it exits, maybe it takes more than 3 seconds to create that directory?

How to get bash to print the output without the fields with zero size when running smem command?

Here is the 'smem' command I run on the Redhat/CentOS Linux system. I expect the output be printed without the fields with zero size however I would expect the heading columns.
smem -kt -c "pid user command swap"
PID User Command Swap
7894 root /sbin/agetty --noclear tty1 0
9666 root ./nimbus /opt/nimsoft 0
7850 root /sbin/auditd 236.0K
7885 root /usr/sbin/irqbalance --fore 0
11205 root nimbus(hdb) 0
10701 root nimbus(spooler) 0
8446 trapsanalyzer1 /opt/traps/analyzerd/analyz 0
50316 apache /usr/sbin/httpd -DFOREGROUN 0
50310 apache /usr/sbin/httpd -DFOREGROUN 0
3971 root /usr/sbin/lvmetad -f 36.0K
63988 root su - 0
7905 ntp /usr/sbin/ntpd -u ntp:ntp - 4.0K
7876 dbus /usr/bin/dbus-daemon --syst 44.0K
9672 root nimbus(controller) 0
7888 root /usr/lib/systemd/systemd-lo 0
63990 root -bash 0
59978 postfix pickup -l -t unix -u 0
3977 root /usr/lib/systemd/systemd-ud 736.0K
9016 postfix qmgr -l -t unix -u 0
50303 root /usr/sbin/httpd -DFOREGROUN 0
3941 root /usr/lib/systemd/systemd-jo 52.0K
8199 root //usr/lib/vmware-caf/pme/bi 0
8598 daemon /opt/quest/sbin/.vasd -p /v 0
8131 root /usr/sbin/vmtoolsd 0
7881 root /usr/sbin/NetworkManager -- 8.0K
8364 root /opt/puppetlabs/puppet/bin/ 0
8616 daemon /opt/quest/sbin/.vasd -p /v 0
23290 root /usr/sbin/rsyslogd -n 3.8M
64091 root python /bin/smem -kt -c pid 0
7887 polkitd /usr/lib/polkit-1/polkitd - 0
8363 root /usr/bin/python2 -Es /usr/s 0
53606 root /usr/share/metricbeat/bin/m 0
24631 nagios /usr/local/ncpa/ncpa_passiv 0
24582 nagios /usr/local/ncpa/ncpa_listen 0
7886 root /opt/traps/bin/authorized 76.0K
7872 root /opt/traps/bin/pmd 12.0K
8374 root /opt/puppetlabs/puppet/bin/ 0
7883 root /opt/traps/bin/trapsd 64.0K
----------------------------------------------------
54 10 5.1M
Like this?:
$ awk '$NF!=0' file
PID User Command Swap
7850 root /sbin/auditd 236.0K
...
7883 root /opt/traps/bin/trapsd 64.0K
----------------------------------------------------
54 10 5.1M
But instead of using the form awk ... file you'd probably like to smem ... | awk '$NF!=0'.
Could you please try following, for extra precautions removing the space from last fields(in case it is there).
smem -kt -c "pid user command swap" | awk 'FNR==1{print;next} {sub(/[[:space:]]+$/,"")} $NF==0{next} 1'

Bash completion for Camel.CaseNames (cd CCN<tab> => cd Camel.CaseName)

I'm looking for a way to implement completion for file/directory names of the kind
Foo.Bar.Baz/
Foo.Bar.QuickBrown.Fox/
Foo.Bar.QuickBrown.Interface/
Foo.Bar.Query.Impl/
where the completion would work like
~ $ cd QI<tab><tab>
Foo.Bar.QuickBrown.Interface/ Foo.Bar.Query.Impl/
~ $ cd QIm<tab><enter>
~/Foo.Bar.Query.Impl $
However, my simplistic approach of building a glob pattern from the input (eg. QIm -> *Q*I*m) does not exactly work for files / directories sharing the same prefix. In the case above, I get
~ $ cd QI<tab><tab>
Foo.Bar.QuickBrown.Interface/ Foo.Bar.Query.Impl/
~ $ cd Foo.Bar.Qu<tab><tab>
Foo.Bar.QuickBrown.Fox/ Foo.Bar.QuickBrown.Interface/ Foo.Bar.Query.Impl/
i.e. bash replaces the current word with the longest common prefix of the possible completions, which in this case results in larger completion set.
Here's my completion function:
_camel_case_complete()
{
local cur pat
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
pat=$(sed -e 's/\([A-Z]\)/*\1*/g' -e 's/\*\+/*/g' <<< "$cur")
COMPREPLY=( $(compgen -G "${pat}" -- $cur ) )
return 0
}
Any hints how to fix this without breaking normal filename / directory completion?
See following example:
% ls -l
total 20
-rw-r--r-- 1 root root 315 2016-06-02 18:30 compspec
drwxr-xr-x 2 root root 4096 2016-06-02 17:56 Foo.Bar.Baz
drwxr-xr-x 2 root root 4096 2016-06-02 17:56 Foo.Bar.Query.Impl
drwxr-xr-x 2 root root 4096 2016-06-02 17:56 Foo.Bar.QuickBrown.Fox
drwxr-xr-x 2 root root 4096 2016-06-02 17:56 Foo.Bar.QuickBrown.Interface
% cat compspec
_camel_case_complete()
{
local cur=$2
local pat
pat=$(sed -e 's/[A-Z]/*&/g' -e 's/$/*/' -e 's/\*\+/*/g' <<< "$cur")
COMPREPLY=( $(compgen -G "${pat}" ) )
if [[ ${#COMPREPLY[#]} -gt 1 ]]; then
# Or use " " instead of "__"
COMPREPLY[${#COMPREPLY[#]}]="__"
fi
return 0
}
complete -F _camel_case_complete cd
% . ./compspec
% cd QI<TAB><TAB>
__ Foo.Bar.QuickBrown.Interface
Foo.Bar.Query.Impl
% cd QIm<TAB>
% cd Foo.Bar.Query.Impl<SPACE>

Perl's retrieval of file create time incorrect

I am attempting to use perl to rename files based on the folder they are in and the time created. Files GOPR1521.MP4 and GOPR7754.MP4 were created on two different cameras at the same time and date, and I want to be able their names to indicate that. For example .../GoProTravisL/GOPR1521.mp4 created at 12:32:38 should become 123238L_GOPR1520.mp4, and GOPR7754.MP4 becomes 123239R_GOPR7754.MP4. Right now the only problem is the time stamps. I would think its a problem with being wrong timezone or hour offset, but the minutes are off too. Is there something in perl I am missing when getting time stamps? Below is the perl code, what it outputs for times for each file, and what Finder on OS X says the creation times are.
Code:
#!/usr/bin/perl
use Time::Piece;
use File::stat;
use File::Find;
use File::Basename;
use File::Spec;
#files = <$ARGV[0]/>;
find({ wanted => \&process_file, no_chdir => 1 }, #files);
sub process_file {
my($filename, $dirs, $suffix) = fileparse($_,qr/\.[^.]*/);
if ((-f $_) && ($filename ne "" )) {
#print "\n\nThis is a file: $_";
#print "\nFile: $filename";
#print "\nDIR: $dirs";
my(#parsedirs) = File::Spec->splitdir($dirs);
my #strippeddirs;
foreach my $element ( #parsedirs ) {
push #strippeddirs, $element if defined $element and $element ne '';
}
$pardir = pop(#strippeddirs);
#print "\nParse DIR: ", $pardir;
#print "\nFile creation time: ";
$timestamp = localtime(stat($_)->ctime)->strftime("%H%M%S"); #gives time stamp
print $timestamp;
$newname = $timestamp . substr($pardir,-1) ."_". $filename . $suffix;
print "\nRename: $dirs$filename$suffix to $dirs$newname\n";
#rename ($dirs . $filename . $suffix,$dirs . $newname) || die ( "Error in renaming: " . $! );
} else {
print "\n\nThis is not file: $_\n";
}
}
Output of time stamps for each file:
/Volumes/Scratch/Raw/2016-03-21/GoProTravisL/
File: GOPR1520
File creation time: 05-55-21
File: GOPR1521
File creation time: 05-56-18
File: GOPR1522
File creation time: 05-57-44
File: GOPR1523
File creation time: 05-58-49
File: GP011520
File creation time: 05-59-53
/Volumes/Scratch/Raw/2016-03-21/GoProTravisR
File: GOPR7754
File creation time: 06-02-48
File: GOPR7755
File creation time: 06-04-19
File: GOPR7756
File creation time: 06-06-27
File: GOPR7757
File creation time: 00-06-16
File: GP017754
File creation time: 00-19-30
File: GP027754
File creation time: 00-22-20
Actual file times using ls:
MacTravis:2016-03-21 travis$ ls -lR /Volumes/Scratch/Raw/2016-03-21
total 0
drwxr-xr-x 8 travis admin 272 Apr 9 21:25 GoProTravisL
drwxr-xr-x 9 travis admin 306 Apr 9 21:25 GoProTravisR
/Volumes/Scratch/Raw/2016-03-21/GoProTravisL:
total 21347376
-rw------- 1 travis admin 4001240088 Mar 21 12:04 GOPR1520.MP4
-rw------- 1 travis admin 1447364149 Mar 21 12:31 GOPR1521.MP4
-rw------- 1 travis admin 2140532053 Mar 21 12:45 GOPR1522.MP4
-rw------- 1 travis admin 1649133454 Mar 21 13:00 GOPR1523.MP4
-rw------- 1 travis admin 1691562945 Mar 21 12:21 GP011520.MP4
/Volumes/Scratch/Raw/2016-03-21/GoProTravisR:
total 31941008
-rw------- 1 travis admin 4001129586 Mar 21 12:04 GOPR7754.MP4
-rw------- 1 travis admin 2166255754 Mar 21 12:31 GOPR7755.MP4
-rw------- 1 travis admin 3202301883 Mar 21 12:45 GOPR7756.MP4
-rw------- 1 travis admin 2466803806 Mar 21 12:08 GOPR7757.MP4
-rw------- 1 travis admin 4001257192 Mar 21 11:27 GP017754.MP4
-rw------- 1 travis admin 516025454 Mar 21 11:29 GP027754.MP4
ctime is the "time of last status change", which I believe is the time the inode was last modified. It is NOT the file's creation time[1]. ls lists the file modification time, so simply change from using ctime to using mtime.
Historically, the time at which a file was created wasn't tracked by file systems used on unix file systems. Some newer file systems track it, but I am unsure how to access it (nor is it needed here).

Why does `Dir[directory_path].empty?` return `false` all the time?

Dir[directory_path].empty? returns false all the time. The behavior is the same whether or not I run irb as root:
$ ll
total 12
drwxrwxrwx 2 ndefontenay ndefontenay 4096 Aug 12 12:11 ./
drwxrwxrwx 4 ndefontenay ndefontenay 4096 Aug 5 11:45 ../
-rw-rw-r-- 1 ndefontenay ndefontenay 8 Aug 12 12:11 test
$ irb
> Dir["/opt/purge_entitlement/in"].empty?
=> false
> exit
$ sudo irb
> Dir["/opt/purge_entitlement/in"].empty?
=> false
If someone could shed some light on this problem, it would be pretty helpful.
Dir[].empty? returns false all the time
It should,because it always contains the parent directory (..), and the directory itself (.),that you didn't take care of.
This is not an answer to your question, but to avoid the problem of getting . and .. in the list, use Dir.glob instead of Dir.[]. You will probably get true for this:
Dir.glob("/opt/purge_entitlement/in/*").empty?

Resources