how can find directory - bash

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?

Related

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).

mkdir recursion with permissions

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/

No response from [ -f /path/to/file ]

I am trying to get my Capistrano deploy script working, but it is not doing the symlinking as it is configured to do as shown below.
set :linked_files, %w{config/database.yml}
set :linked_dirs, %w{log tmp vendor/bundle public/system}
When it runs the related command, I get the following:
WARN [SKIPPING] No Matching Host for /usr/bin/env [ -f /path/to/shared/config/database.yml ]
If I run this command on the server, either through ssh or through logging onto the server and running the command, I get no response from the command.
user: ~
$ [ -f /path/to/shared/config/database.yml ]
user: ~
$
The file does exist in the specified location and has permissions.
user: ~
$ ll /path/to/shared/config/
total 4.0K
drwxrwxr-x 2 user group 33 Nov 30 10:58 .
drwxrwxr-x 7 user group 89 Nov 30 10:58 ..
-rwxrwxr-x 1 user group 805 Nov 30 10:58 database.yml
user: ~
Shouldn't this return a true or a false, instead of nothing? Is there a configuration I may have changed that suppresses the output? I get no response at all whether the file exists or not.
In your response to the actual question you ask, test (which is what [ is an alias for) does in fact not return output to stdout. It returns an exit code.
user: ~
$ [ -f /path/to/shared/config/database.yml ] # if the file exists
user: ~
$ echo $?
0
user: ~
$ [ -f /path/to/shared/config/database.yml ] # if the file does not exist
user: ~
$ echo $?
1
test -f /path/to/file (or [ -f /path/to/file ]) yields an exit code of 0 if the file exists or 1 if it does not. If you want to check that a file is there and echo the path to it, try:
[ -f /path/to/file ] && echo "/path/to/file"

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?

How to get last modified file in a directory to pass to system commands using Ruby?

I'm trying to do some dev-ops. I need to grab the last modified file in a directory to pass the filename to another command.
If I had a list of files outputted with ls -la in Ruby:
-rw-r--r-- 1 163929215 2012-11-26 00:02 appname_20121126_000002.tgz
-rw-r--r-- 1 164051752 2012-11-27 00:02 appname_20121127_000002.tgz
-rw-r--r-- 1 164160113 2012-11-28 00:02 appname_20121128_000002.tgz
-rw-r--r-- 1 164284597 2012-11-29 00:02 appname_20121129_000004.tgz
-rw-r--r-- 1 164342795 2012-11-30 00:02 appname_20121130_000003.tgz
-rw-r--r-- 1 164448312 2012-12-01 00:02 appname_20121201_000003.tgz
-rw-r--r-- 1 164490727 2012-12-02 00:02 appname_20121202_000002.tgz
-rw-r--r-- 1 164546124 2012-12-03 00:02 appname_20121203_000001.tgz
-rw-r--r-- 1 164594711 2012-12-04 00:02 appname_20121204_000002.tgz
How could I scan this with Ruby and pull the last file?
Is something like this even possible?
There's no need to shell out to ls and parse its output at all. Ruby gives you standard library methods to fetch directory contents and examine file mtimes. Here's a ruby method to return the name of a file in a directory with the latest mtime.
def last_modified_in dir
Dir.glob( File.join( dir,'*' ) ).
select {|f| File.file? f }.
sort_by {|f| File.mtime f }.
last
end
irb> system 'mkdir -p /tmp/foo'
irb> system 'rm /tmp/foo/*'
irb> ('a'..'c').each { |f| system "touch /tmp/foo/#{f}"; sleep 1; }
irb> puts last_modified_in '/tmp/foo'
# => /tmp/foo/c

Resources