procmail rule to write to two folders - procmail

I have a procmail rule that looks for email sent to a specific address and saves it to a folder. The rule looks like this and works just fine.
:0:
* ^TOarchive#extraspecialbitter.com
/home/pablo/mail/archive
I'd like it to write to a second folder as well, but so far everything I've tried hasn't worked. A second rule for the same "TO" address is ignored, as is a second folder following the first, i.e.:
:0:
* ^TOarchive#extraspecialbitter.com
/home/pablo/mail/archive
/home/pablo/mail/new
I've also tried putting both folders on the same line with delimiters of space, comma and "|", but no joy. The first folder is always used, and the second ignored. Any ideas?

Maybe this would work (don't miss c to make carbon-copy).
:0 c:
* ^TOarchive#extraspecialbitter.com
/home/pablo/mail/archive
:0:
* ^TOarchive#extraspecialbitter.com
/home/pablo/mail/new
Or (should work the same):
:0
* ^TOarchive#extraspecialbitter.com
{
:0 c:
/home/pablo/mail/archive
:0:
/home/pablo/mail/new
}

Related

procmail - using {} won't deliver to mbox

I'm trying to use procmail to tidy up some old email into my thunderbird mbox file, however I can't seem to get it to file into an mbox file when using braces. Doing the simple test below with and without braces provides different outcomes - what am I missing, please:
SHELL=/bin/sh
# --- OPTIONAL, USED FOR DEBUGGING (comment out)
VERBOSE=yes
LOGABSTRACT=all
LOGFILE="procmail.log"
MAILDIR=/home/jake/windows/Thunderbird/Mail/Local\ Folders
DEFAULT=/home/jake/done/
# goes into MAILDIR/processed
:0
processed
# goes into DEFAULT/msg.gAmAAAAA4F/etc.
:0
{
processed
}
Your second recipe is basically a syntax error, though the Procmal parser actually parses it into an expression which however means something totally different than you intended. Here's what you have actually written, spelled out in full.
:0
{
processed=''
}
So Procmail enters the braces, performs the assignment, exits the braces, and delivers to $DEFAULT when it falls through to the end of the recipe file.
To actually deliver into a file, you need a full recipe like
:0
{
:0
processed
}
... but obviously the outer recipe with the braces is completely redundant here.
The fact that a symbol on its own gets parsed as an empty variable assignment which clears the variable named by that symbol is unobvious and wildly confusing not only to beginners, so don't feel particularly bad that you couldn't figure this one out.
With VERBOSE=yes you should actually find that the log file shows you exactly this chain of events. Your log file will end up in your MAILDIR so perhaps you didn't find it...?

procmail: conditioning on multiple fields

I would like to store e-mails sent by me to others using the "From" field to a folder called "/sent"
So, I use:
:0:
*^From.*user#outlook.com
$HOME/Mail/sent/.
And it used to work fine. However, now I am also forwarding my e-mail from the address:user#outlook.com, what is happending is that the e-mail envelope contains the header: Resent-From.*user#outlook.com so all forwarded e-mail is being saved to the sent folder.
Is it possible to have a double condition. That is something that says that if both Resent-From and From have *user#outlook.com, then it should go to the sent-folder. In other words, is it possible to use a AND or OR or Negation condition.
Update: The provided solution is correct. I was making an error in that I had neglected the ":". Thanks for both the solution and the patience. I also learnt a number of things and about a number of resources, for which also I am grateful,
Thanks!
Procmail by default does exactly what you ask. Multiple conditions will be ANDed together. The first one which fails causes the recipe to be abandoned; if they all succeed, the action is taken.
:0 # second colon removed - don't use lock on directories
* ^From:(.*\<)?user#outlook\.com
* ^Resent-From:(.*\<)?user#outlook\.com
$HOME/Mail/sent/.
Notice also how I modified your regex to tighten it up.
To do NOT, add a ! in front of the condition. To do OR, you can negate both conditions, and take the action in the "else" part (de Morgan's law).
:0
* ! First condition
* ! Other condition
{ } # do nothing
:0E # else, meaning at least one was true
action
Of course, if both conditions are regular expressions, you can simply use the regex or operator.
:0
* First condition|Other condition
action

gitignore all files except all java files in subdirectory

I've tried a bunch of different methods.
1.
*
!.gitignore
!./src/com/AleXander/*
2.
/*
!.gitignore
!src/com/Alexander/*.java
3.
*
!.gitignore
!./*.java
as well as multiple other variations of this. I came across this question that looks like it's using Regex. Is regex needed for this to work? Any ideas?
I also tried these regex patterns but I am not the best at regex.
1.Logic: ignore all files ending with the file extension pattern "java"
*
!.gitignore
!*.[^java$]
2.Logic: ignore all files ending with a "j" followed by an "a" with anything else after that.
*
!.gitignore
!*.j[^a]*
Ignoring * is a bad idea.
This will ignore every file and every directory in every part of your repository.
Especially git will not look at all at ignored directories. Therefore the exceptions you define later will have no effect at all.
There are quite longish include/exclude hacks to make something like this work, but usually the best way is to just explicitly ignore the files you want to ignore and avoid any exceptions whenever possible.
If you feel the need for some more complicated ignore rules this is usually an indicator that your repository layout needs a better structure.

Discard kernel-ML patch-mails which are not from me, send to me or as response on my mails?

as the linux kernel mailing list is really noisy, I want to discard all mails which are send to my mailbox from the LKML, but which are not from me, to me or as answer to one of my mails. I do already do some filtering and redirect all patch-mails (including [PATCH at the beginning of the subject) to another inbox as the "normal" LKML mails. But it is still much too much.
How to do this with procmail?
What I have atm:
:0
* ^Sender:\ linux-kernel-owner#vger\.kernel\.org
* (PATCH|patch)
$MAILDIR/ml.kernel_org.linux-kernel.patches/
The real challenge here is to articulate how to reliably identify messages which are replies to something you wrote. Are you satisfied with excluding messages which are To: or Cc: yourself?
:0
* ^Sender: linux-kernel-owner#vger\.kernel\.org\>
* ! ^From: Your Self <you#example\.net>
* ! ^TO_you#example\.net\>
/dev/null
(obviously, edit the addresses to match what your mail client really puts there).
Or perhaps you have a vanity domain, in which case (properly constructed) replies will have an easily identifiable Message-Id of yours at the start of References:?
:0
* ^Sender: linux-kernel-owner#vger\.kernel\.org\>
* ! ^From: Your Self <you#example\.net>
* ! ^TO_you#example\.net\>
* ! ^References:[ ]*<[^<>#]*#yourdomain\.example\.net>
/dev/null
(the whitespace inside the square brackets should be a tab and a space).
Or you could expand that a bit to look for your domain anywhere in References:, to also include replies to replies to yourself, if you want that.
Or you could keep a local copy of all your outgoing message-id:s and look for them in References:, but that is already a significant endeavor which I will only point out as a possibility if you cannot use any of the above. (I do believe it has been hashed out in more detail before, perhaps on the Procmail mailing list.)
As an aside, I would change the "patch" rule to only examine the Subject: line. A match on "patch" in any other header is extremely likely to be a false positive. If you want to examine the body, you need extra flags, perhaps like this:
:0
* ^Sender: linux-kernel-owner#vger\.kernel\.org\>
{
:0
* ! B ?? \<patch\>
* ! ^Subject:(.*\<)?patch\>
{ } # empty "then", just so we can continue to "else"
:0E
$MAILDIR/ml.kernel_org.linux-kernel.patches/
# While we are inside these braces, let's continue with other LKML stuff
:0
* ! ^From: Your Self <you#example\.net>
* ! ^TO_you#example\.net
/dev/null
# Any additional LKML recipes? Add them here
# Anything which falls through here is regular LKML
:0
$MAILDIR/ml.kernel_org.linux-kernel/
}
(This can obviously be refactored in a number of different ways. Remember De Morgan's laws: NOT (A OR B)<=> NOT A AND NOT B.)
As a safety measure, you might want to look for messages which actually carry a patch as an attachment, rather than filter the discussion about such messages? That can also become quite complex, because there is a number of different ways to represent a patch as a MIME attachment (and some are also sent completely in-line, in a regular text/plain part amongst other text) but that isn't insurmountable, either, just significant drudgery.

Regex and shell - multiple recursive rename

I have a folder with several hundreds of folders inside it. These folders contain another folder each, called images, and in this folder there is sometimes a strictly numerically named .jpg file. Sometimes there are other JPG files in the folder as well, but these need to be ignored if they aren't strictly numeric.
I would like to learn how to write a script which would, when run in a given folder, traverse every single subfolder and look for this numeric file. It would then add the "_n" suffix to a copy of each, if such a file does not already exist.
Can this be done through the unix terminal easily?
To be more specific, this is the structure I'm dealing with:
master folder
18556
images
2234.jpg
47772
images
2234.jpg
2234_n.jpg
some_pic.jpg
77377
images
88723
images
22.jpg
some_pic.jpg
After the script is run, the situation would look like this:
master folder
18556
images
2234.jpg
2234_n.jpg
47772
images
2234.jpg
2234_n.jpg
some_pic.jpg
77377
images
88723
images
22.jpg
22_n.jpg
some_pic.jpg
Update: Sorry about the typo, I accidentally put 2235 into 47772.
Update 2: Regarding the 2nd comment on the mathematical.coffee's answer, the OS I am currently on (at work) is MacOS, but my main machines are running CentOS and Ubuntu at home, so I just assumed my situation applies to all unix based systems.
You can use the -regex switch to find to match /somefolder/images/numeric.jpg:
find -type f -regex './[^/]+/images/[0-9]+\.jpg$'
Edit: refinement from #JonathanLeffler: add -type f to find so it only finds files (ie don't match a directory called '12345.jpg').
The ./[^/]+/ is for the first folder (if that first folder is always numeric too you can change it to [0-9]+).
The [0-9]+\.jpg$ means a jpg file with file name only being numeric.
You might want to change the jpg to jpe?g to allow .jpeg, but that's up to you.
Then it's a matter of copying these to xxx_n.jpg.
for f in $(find -type f -regex './[^/]+/images/[0-9]+\.jpg$')
do
# replace '.jpg' in $f (filename) with '_n.jpg'
newf=${f/\.jpg/_n\.jpg}
# see if this new file exists
if [ ! -f $newf ];
then
# if not exists, copy it.
cp "$f" "$newf"
fi
done
What should be the logic behind the renames in Folder 47772? If we assume you want to rename all the files just consisting of numbers to numbers + _n
With mmv you could write it like:
mmv "[0-9][0-9]*.jpg" "#1#2#3_n.jpg"
Note: mmv is for moving; mcp is for copying, and so is more appropriate to this question.
Question of Vader:
Well I checked the man page and the problem is that it's a bit strange.
I was thinking [0-9]* would match zero or more numbers. I turns out that this assumption was wrong.
The problem is that I could not tell I want two or more numbers at the start of the name.
So [0-9][0-9]* matches a name starting with at least two numbers (after that it takes all the rest up to the .. Now every [0-9] is one pattern and so I had to make the to pattern into:
"#1#2#3_n.jpg" With e.g 1234.jpg I have #1 = 1; #2 = 2, #3 = 34 So
#1#2#3 -> 1234; _n appends the _n and .jpg the extension
However it would rename also files with 12some_other_stuff.jpg sot 12some_other_stuff_n.jpg. It's not ideal but achieves in this context what was intended.