How do I write an SSIS Expression to extract one folder name from a fully qualified file name - sql

I have an SSIS package with an ForEach File Enumerate loop (Fully Qualified Name) with an FTP task within in.
The package when executed will go through the files in the subfolders within the following directory
C:\Test\Test2\ABC\
*.txt
And it will post the files to an FTP site.
I have a defined variable called #[User::Filename] within the foreach loop.
But there are folders within the FTP and I want the files to go to based on the Folder they are taken from on the C drive.
C:\Test\Test2\ABC\A\1.txt
C:\Test\Test2\ABC\B\2.txt
C:\Test\Test2\ABC\C\3.txt
File 1.txt should go to the FTP folder Called \FTP\A
File 2.txt should go to the FTP folder Called \FTP\B
File 3.txt should go to the FTP folder Called \FTP\C
My original thought was to make the remote path a variable and piggy back off the the foreach loop variable Fully qualified name.
To do this I created a variable called #[User::FilenameFTP] and inputted the following into the expression
"//FTP//" +
RIGHT(
(LEFT(#[User::Filename], ABS((FINDSTRING(#[User::Filename], "//", 5)))),
ABS((FINDSTRING(#[User::Filename], "//", 5)-1)) - ABS((FINDSTRING(#[User::Filename], "//",4)+1))
)
I thought this formula would give me the filename in the C drive which the file is coming from and I used this as the Remote Path variable within the FTP task. But when I run it the files still go into \FTP\ and not into the subfolders.
I ran a script task on this and the output isnt showing what I want either. What am I doing wrong? Can this not be done this way editing the variable within the foreach loop?

If your drive names are coming in (more or less) as you have them shown, then those should be backslashes ("\\") instead of forward slashes in your expression. Might not be the issue, but I changed them to play around with this.
Using the C folder string, in the expression as written, ABS((FINDSTRING(#[User::Filename], "\\", 5)-1)) and ABS((FINDSTRING(#[User::Filename], "\\",4)+1)) both evaluate to 19, so the expression comes down to RIGHT(<<String>>,0), and, from the documentation, If integer_expression is zero, the function returns a zero-length string.. So you're not appending anything to the end of the FTP base folder name.
Down and Dirty Fix
We could probably mess around with all that LEFT and RIGHT and FINDSTRING, but if you know that the folder name you're after will always be the fifth element in your fully qualified name (which your expression is already dependent on) you can get there faster just using TOKEN, and specifying the fifth element of your slash-delimited string:
"//FTP//" + TOKEN( #[User::Filename],"\\",5) +"//"
Which evaluates to //FTP//C//.
More Sustainable Fix
On the other hand, if you want to future-proof your code a little, in anticipation of the day that you add or eliminate a level of folder hierarchy, I would suggest extracting the last folder name, without regard to how many levels of folder come first.
We can do that using SUBSTRING and some clever REVERSE work, with due credit to KeithL for this answer, that got me rolling.
SUBSTRING takes three arguments. We have our string #[User::Filename], so that's one. The second is the starting position from the left end of the string, and the third is the number of characters to extract.
To get the starting position, we'll find the position of the second to last slash using REVERSE to count characters from the right hand end of the string:
FINDSTRING(REVERSE( #[User::Filename]),"\\",2) (evaluates to 8 here)
So our starting position is the total length of the string, minus the number of characters back to the second to last slash.
LEN( #[User::Filename]) - FINDSTRING(REVERSE( #[User::Filename]),"\\",2) (=17)
We can get the number of characters to pull by subtracting the reversed position of the last slash from the reversed position of the second to last slash, then subtracting one more, since we don't want that trailing slash in our string yet.
FINDSTRING(REVERSE( #[User::Filename]),"\\",2)
- FINDSTRING(REVERSE( #[User::Filename]),"\\",1) - 1 (= 1 in our example)
And there are our three arguments. Putting those all together with your base folder name (and I added a trailing slash. If that doesn't work for you, take it out of there!):
"//FTP//"
+ SUBSTRING(
#[User::Filename] ,
LEN( #[User::Filename]) - FINDSTRING(REVERSE( #[User::Filename]),"\\",2),
FINDSTRING(REVERSE( #[User::Filename]),"\\",2)
-FINDSTRING(REVERSE( #[User::Filename]),"\\",1)-1 )
+ "//"
Evaluates to //FTP//C//.
Now, when the powers that be decide to "clean up" that source server, and the Test2 layer disappears all of a sudden, or things get crazy, and you bury this all one layer deeper, your code will still work.
Side Note
If you're really using drive letters in your file path names, like C:\, be aware that when you're running your packages locally, that's your C:\ drive the package is using, but when you deploy this, it'll be looking around on the server's C:\ drive, and it just might not like what it finds, or more likely, doesn't find there.

Related

PATHS: trailing backslash or not trailing backslash?

I've many VBA scripts and functions where I read a manually inserted (in Excel cell) local disk paths and I'm still confused about whether to normalize the inserted paths by adding or trimming the trailing backslash.
What do you use as the general standard? with or without the trailing backslash?
My confusion is fueled by the fact that for example ActiveWorkbook.path returns a path without trailing backslash while the CopyFile (FileSystemObject) method for the "Destination" parameter wants the trailing backslash otherwise it considers it as a file instead than a directory (and can give unexpected Permission denied errors)
The general idea is to always end a directory's name with a backslash. This is advised in the URL you mention, but there are quite some other situations as well (check my answer on a regularly occuring xcopy problem).
As mentioned: when you don't put a backslash, the question might arise "Is it a file or a directory?". Putting the backslash solves that question.
In top of that, while programming, regularly you might have following situation:
complete_filename = path + filename
Obviously, if you have forgotten to put the backslash at the end, this might cause problems (e.g. you don't want to create a file, called "C:\Tempoutput.txt" instead of "C:\Temp\output.txt", I presume? :-) )

Find longest file in the project IntelliJ IDEA

Hello I want to know any trick or shortcut by which one can know which is the longest file in project.
i.e which file has the longest lines of code.Is there any shortcut or plugin available?
I believe the OP was asking about the length of file, not the length of single line. You can try with such iteration:
(.*\n){100,}
(.*\n){1000,}
(.*\n){10000,}
Although this is kind of hacky it still works.
You can search your whole project using the regex repetition pattern. Just right-click your project folder in the project structure view and choose "Find in path...". Be sure to check "Regex" in the search window that appears.
So you'll start out and match any line with any length in your project
^.$
(If you're not familiar with regex: ^ and $ are used to denote the beginning and end of a line and . matches any character)
Then you gradually increase the number of matched repetitions
^.{1,}$
^.{10,}$
^.{100,}$
^.{1000,}$
(You use {start, end} to indicate to interval of repetitions. If you leave end blank it will match anything from start)
Using this you will soon be left with the longest line(s) in your project.
As I said it's kinda hacky but it's also quick and works if you don't have to automate the task.
Hope this helps you!

syslog-ng match and filter is not working the way I want

I have following messages
1)"customer1"," 5","0","".....
2)"customer2"," 5","0",""....
3)"customer3"," 5","0",""...
4)""," 5","0",""
5)""," 5","0",""
What I want to achieve is based on first value in double quotes I want to create folders and then writing logs in the respective folder only and whenever double quote is blank send those logs in Others folder.With the following configuration I am able to create folder like (customer1,customer2 and customer3). Problem Occurs when I have blank value at the first place like log 4 and 5.
syslog-ng.conf
filter c1 {match('(^"")' flags("store-matches") type("pcre") value("MESSAGE") );};
destination d1 {file("/opt/data/cef/other/${DAY}${MONTH}${YEAR}_other.log");};
log {source(s_udp);filter(c1);destination(d1);};
filter c2 {match('(?<=")([\w\s]*)(?=")' flags("store-matches") type("pcre") value("MESSAGE") );};
destination d2 {file("/opt/data/cef/$1/${DAY}${MONTH}${YEAR}_$1.log");};
log {source(s_udp);filter(c2);destination(d2);};
First filter checks if the first double quote is empty or just like "" and it writes those logs into Others folder.Problem is with the second filter it matches everything between "". So it works fine if it has value but misbehave if it is empty .So it writes this log into a file with the name 03_06_2017.log in /opt/data/cef folder. I am not sure why it is creating a separate file .
Please help .
Regards
VG
I think it would be easier to use a csv-parser: https://www.balabit.com/documents/syslog-ng-ose-latest-guides/en/syslog-ng-ose-guide-admin/html/csv-parser.html
If the number of columns in the messages varies, and you only need the first column for your filter, then you can use the greedy flag to take care of the other columns.

How to use FILE_MASK parameter in FM EPS2_GET_DIRECTORY_LISTING

I am trying to filter files using FILE_MASK parameter in EPS2_GET_DIRECTORY_LISTING to reduce time searching all files in the folder (has thousands of files).
File mask I tried:
TK5_*20150811*
file name in the folder is;
TK5_Invoic_828243P_20150811111946364.xml.asc
But it exports all files to DIR_LIST table, so nothing filtered.
But when I try with;
TK5_Invoic*20150811*
It works!
What I think is it works if I give first 10 characters as it is. But in my case I do not have first 10 characters always.
Can you give me an advice on using FILE_MASK?
Haven’t tried, but this sounds plausible:
https://archive.sap.com/discussions/thread/3470593
The * wildcard may only be used at the end of the search string.
It is not specified, what a '*' matches to, when it is not the last non-space character in the FILE parameter value.

What is the meaning of the file names flanked by the '#' sign and how can I remove them?

When I do the 'ls' command in the terminal on my Raspberry Pi 2, I see different types of names of files, some like "#example.cpp#", as well as others like "homework1.cpp~".
What do these two file types mean, and how can I get rid of them? Simply using the 'rm' command doesn't seem to be working for me. Thanks!
Some applications will create a copy of a file and use special characters when creating the filename for the copy. For instance some text editors will make a copy of a file you are starting to edit by using the same name and adding a tilde character (~) to the end of the file. That way you will have a backup of the file that you are about to edit.
Another reason would be if an application is processing the file into a temporary file with the temporary file then being used for the next step. For example perhaps the C/C++ compiler is reading the file homework1.cpp with the C Preprocessor to generate the temporary file #homework1.cpp# which is then compiled by the compiler to generate the object code file.
I am not familiar with raspberry pi so am not sure as to what may be creating the filenames with the pound sign (#) on the front and back. Perhaps it is the C++ compiler. I am pretty sure the files with the tilde character on appended to the end of the file name is a back file from vi or vim containing a copy of the file at the time it was last opened with the text editor.
One thing that you could do is to look in those files to see what is there using a Linux command or a text editor. If you use a text editor I would copy the file to another folder as a back up and then look at it there.
Edit: Someone just posted and then deleted an answer which also mentioned about how to remove these files.
What I read was that the rm command is used however for some kinds of special characters you will need to use quotes around the name and you may also need to use an escape to escape certain special characters.
The command shell reads the command line you type in and makes changes to the text before passing it on to the command you type in. So if the filename has a space in it, say jj Johny then when you remove the file you have to specify rm "jj Johny" since spaces are used by the command processor to separate out arguments.
The other poster mentioned that you had to escape out the pound sign (#) using the back slash character in order to prevent it from being modified by the command processor.