Zsh completion caching policy explained - autocomplete

I'm writting some zsh functions using the powerful completion feature. The computation of my completions take some times and I want to make use of the completion caching policy. From the zsh manual (https://zsh.sourceforge.io/Doc/Release/Completion-System.html) I found this code snippet
example_caching_policy () {
# rebuild if cache is more than a week old
local -a oldp
oldp=( "$1"(Nm+7) )
(( $#oldp ))
}
I couldn't find any explanation on the (Nm+7) syntax, what does Nm means ? With try and error I could find out that for example Nms+1 would change the cache policy to 1 second, while Nmh+1 to 1 hour. But where can I find the general (NmX+N) construct explanation ?
Same what does exactly means the line (( $#oldp )) ?

I can explain the (Nm+7)
man zshexpn, search for Glob Qualifiers
a[Mwhms][-|+]n
files accessed exactly n days ago. Files accessed within the last n days are selected using a negative
value for n (-n). Files accessed more than n days ago are selected by a positive n value (+n). Op‐
tional unit specifiers `M', `w', `h', `m' or `s' (e.g. `ah5') cause the check to be performed with
months (of 30 days), weeks, hours, minutes or seconds instead of days, respectively. An explicit `d'
for days is also allowed.
Any fractional part of the difference between the access time and the current part in the appropriate
units is ignored in the comparison. For instance, `echo *(ah-5)' would echo files accessed within the
last five hours, while `echo *(ah+5)' would echo files accessed at least six hours ago, as times
strictly between five and six hours are treated as five hours.
m[Mwhms][-|+]n
like the file access qualifier, except that it uses the file modification time.
N stands for NULL_GLOB, if zsh matches nothing, it will remove the pattern.
Without this N option, if it matches nothing it will print an error.
Example with 4 files
$ touch lal # = updates file modification date to now
$ ls
lal lil lol tut
$ ls l*(m+7)
lil lol
# files older than 7 days starting with l
$ ls l*(m-7)
lal
# files younger than 7 days starting with l
$ ls l*(m+200)
zsh: no match
# no files older than 200 days
$ ls l*(Nm+200)
lal lil lol tut
# N = NULL_GLOB made disappear the non-matching pattern so it's just ls

Related

Perl script to copy logs with timestamp for every hour and paste into different file

First of all, I'm very new to programming and so would need your help in writing a perl script to do the following on windows.
I have a big log file with timestamp (1gb) and its difficult to read the logs as it takes a lot of time to open. so my requirement is to copy the logs from the bigger log file for the last one hour and paste it to another file and then copy the next 1 hr of data to different file(so we will have 24 files for a day). The next day the data in these files needs to be over written or delete & create a new file.
Sample log :
09092016-00:02:00,..................
09092016-00:02:08,..................
09092016-00:02:15,..................
09092016-00:02:18,..................
Please help me with this and thanks for your help in advance.
Thanks,
A simpler solution would be to use the split command to split the files into manageable sizes.
split -l 1000 logfile
Will split your logfile into smaller files of 1000 lines each.
You can then just use grep to find the files that contain the day you need.
grep 09092016 logfile*
for example:
logfile="./log"
while read -r d m y h; do
grep "^$d$m$y-$h" "$logfile" > "partial-${y}${m}{$d}-${h}.log"
done < <(sed -n 's/\(..\)\(..\)\(....\)-\(..\)\(.*\)/\1 \2 \3 \4/p' "$logfile" | sort -u)
easy, but not efficient. It reads the whole big logfile 25x for the split. (1x for gathering the existing ddmmyyyy-hh lines in the log, and again for every different found date-hour.)

day difference between dates and check convert the text in date

My intention of writing a shell-script (ksh) is to list all the files in a directory and check the creted date. If the date exceeds 30 days, the files are zipped in another location.
ksh code :
--extracts the day and date of the file
ls -al | awk '{print $6$7}'
output
May23 Jun13 .......
Now, when i extract the day and date, i believe it is in text. Now, my requirement is to change the text into date and check the created date whether less than 30 days or greater.
However, i googled out an found some good suggestions but none satisfoes mine(as far as i searched).
Could you please suggest as what is required to do?
Thanks in advance.
Don't use ls for this. Use find, e.g.
find . -type f -ctime +30
or similar-type command.

cmd line rename file with date and time

Project moving forwards, I can see why creating .bat files to do things can become addictive!
I can now save somefile.txt at regular intervals, I then rename somefile.txt by adding the time and date to create a unique file name
ren somefile.txt somefile_%time:~0,2%%time:~3,2%-%date:~-10,2%%date:~3,2%%date:~-4,4%.txt
As an example, the code above has just renamed somefile.txt to somefile_1317_13022011.txt (1317hrs on 13th February 2011)
I ran
ren somefile.txt somefile_%time:~0,2%%time:~3,2%-%date:~-10,2%%date:~7,2%%date:~-4,4%.txt
yesterday, it ran successfully until midnight, and then it crashed (syntax error) although it was saving as 12012011 for the date (12th Jan 2011) instead of the correct date of 12022011.
Will the current version ran past midnight? Am I confusing myself with UK vs US date format?
Animuson gives a decent way to do it, but no help on understanding it. I kept looking and came across a forum thread with this commands:
Echo Off
IF Not EXIST n:\dbfs\doekasp.txt GOTO DoNothing
copy n:\dbfs\doekasp.txt n:\history\doekasp.txt
Rem rename command is done twice (2) to allow for 1 or 2 digit hour,
Rem If before 10am (1digit) hour Rename starting at location (0) for (2) chars,
Rem will error out, as location (0) will have a space
Rem and space is invalid character for file name,
Rem so second remame will be used.
Rem
Rem if equal 10am or later (2 digit hour) then first remame will work and second will not
Rem as doekasp.txt will not be found (remamed)
ren n:\history\doekasp.txt doekasp-%date:~4,2%-%date:~7,2%-%date:~10,4%_#_%time:~0,2%h%time:~3,2%m%time:~6,2%s%.txt
ren n:\history\doekasp.txt doekasp-%date:~4,2%-%date:~7,2%-%date:~10,4%_#_%time:~1,1%h%time:~3,2%m%time:~6,2%s%.txt
I always name year first YYYYMMDD, but wanted to add time. Here you will see that he has given a reason why 0,2 will not work and 1,1 will, because (space) is an invalid character. This opened my eyes to the issue. Also, by default you're in 24hr mode.
I ended up with:
ren Logs.txt Logs-%date:~10,4%%date:~7,2%%date:~4,2%_%time:~0,2%%time:~3,2%.txt
ren Logs.txt Logs-%date:~10,4%%date:~7,2%%date:~4,2%_%time:~1,1%%time:~3,2%.txt
Output:
Logs-20121707_1019
Digging up the old thread because all solutions have missed the simplest fix...
It is failing because the substitution of the time variable results in a space in the filename, meaning it treats the last part of the filename as a parameter into the command.
The simplest solution is to just surround the desired filename in quotes "filename".
Then you can have any date pattern you want (with the exception of those illegal characters such as /,\,...)
I would suggest reverse date order YYYYMMDD-HHMM:
ren "somefile.txt" "somefile-%date:~10,4%%date:~7,2%%date:~4,2%-%time:~0,2%%time:~3,2%.txt"
following should be your right solution
ren somefile.txt somefile_%time:~0,2%%time:~3,2%-%DATE:/=%.txt
I took the above but had to add one more piece because it was putting a space after the hour which gave a syntax error with the rename command.
I used:
set HR=%time:~0,2%
set HR=%Hr: =0%
set HR=%HR: =%
rename c:\ops\logs\copyinvoices.log copyinvoices_results_%date:~10,4%-%date:~4,2%-%date:~7,2%_%HR%%time:~3,2%.log
This gave me my format I needed:
copyinvoices_results_2013-09-13_0845.log
problem in %time:~0,2% can't set to 24 hrs format, ended with space(1-9), instead of 0(1-9)
go around with:
set HR=%time:~0,2%
set HR=%Hr: =0% (replace space with 0 if any <has a space in between : =0>)
then replace %time:~0,2% with %HR%
good luck
ls | xargs -I % mv % %_`date +%d%b%Y`
One line is enough.
ls all files/dirs under current dir and append date to each file.
I tried to do the same:
<fileName>.<ext> --> <fileName>_<date>_<time>.<ext>
I found that :
rename 's/(\w+)(\.\w+)/$1'$(date +"%Y%m%d_%H%M%S)'$2/' *

Perl Strange -M Flag in 'If' statement

What is this flag?
if (-M ..filepath..)
what is the '-M' flag?
perldoc -f -M will answer your question...
This is the modification "age" of the file, in fractional days. That is, it is the number of days since the file was modified, as of the script start time (or as of some other time, if you explicitly set the $^T variable).
I sure hope that the actual code is along the lines of -M filepath > ...; just testing -M's result for truth is pointless.
Script start time minus file modification time (aka file modification age), in days.
In other words, it returns the age of OPERAND in days when the program started.
Also see a full list of file test operators in perldoc perlfunc (-X section)
Modification age (measured in days)
from http://www.devshed.com/c/a/Perl/File-Tests-in-Perl/
if we have something like this:
$age = -M FILE;
$age will contain the days since the file was modified.

BASH: How do you "split" the date command?

Cygwin user here (though if there's a suitable solution I will carry it over to K/Ubuntu, which I also use).
I have a Welcome message in my .bashrc that looks like the following:
SAD=(`date +%A-%B-%d-%Y`)
DUB=(`date -u +%k:%M`)
printf "Today's Date is: ${SAD}.\n"
printf "Dublin time is now ${DUB}. (24-Hour Clock)\n"
After numerous attempts to use whitespaces in the variable SAD above, I gave in and used hyphens. But I am, understandably, not satisfied with this band-aid solution. The problem, as I recall, was that every time I tried using quoted space, \s or some similar escape tag, along with the variables listed in the appropriate section of the GNU manpage for date, the variable for Year was either ignored or returned an error. What I do'nt want to have to do is resort to the full string as returned by date, but rather to keep the order in which I have things in the code above.
As I write this, it occurs to me that setting the IFS around this code for the Welcome message may work, provided I return it to defaults afterwards (the above appears at lines 13-17 of a 68-line .bashrc). However, I can't recall how to do that, nor am I sure that it would work.
Generally-speaking, .bashrc files are in valid BASH syntax, aren't they? Mine certainly resemble the scripts I've either written myself or tested from other sources. All I'm missing, I suppose, is the code for setting and unsetting the field separators around this message block.
No doubt anyone who comes up with a solution will be doing a favor not only to me, but to any other relative newbies on the Net taking their first (or thirteenth through seventeenth) steps in the world of shell scripting.
BZT
Putting
SAD=$(date "+%A %B %d %Y")
DUB=$(date -u +%k:%M)
echo "Today's Date is: ${SAD}."
echo "Dublin time is now ${DUB}. (24-Hour Clock)"
in my .bash_profile prints
Today's Date is: Thursday February 18 2010.
Dublin time is now 12:55. (24-Hour Clock)
I think that's what you want.
the problem is your array declaration.
SAD=(date +%A-%B-%d-%Y) just means you are putting the string "date" as element 0, and "+%A-%B-%d-%Y" as element 1. see for yourself
$ SAD=(date +%A-%B-%d-%Y) #<-- this is an array declaration
$ echo ${SAD[0]}
date
$ echo ${SAD[1]}
+%A-%B-%d-%Y
if you want the value of "date" command to be in a variable, use $(..), eg
$ SAD=$(date +%A-%B-%d-%Y)
$ echo ${SAD}
Thursday-February-18-2010
To get spaces, you need to quote the argument to date so that it's a single string. You're also erroneously declaring SAD and DUB as arrays, when what you really meant to do was evaluate them. Try this:
[/tmp]> $(date "+%A %B %d, %Y")
Thursday February 18, 2010
date +%A\ %B\ %d\ %Y
I found the combination that works:
SAD=$(date "+%A %B %d %Y")
echo $SAD
Thursday February 18 2010
Yet another instance when:
It pays to ask a question
It helps to know where to put your double quotes.
date obviously does not know from quoted space, but Bash does, so
it's a matter of "whispering in the right ear."
Thank you ghostdog74.
BZT