How to pass two strings to a PowerShell function? - string

How do I pass $dir and $file, then concatenate them to a single path?
Output:
posh>
posh> pwsh ./worker.ps1
dir is /home/nicholas/powershell/regex a.log
file is
full is /home/nicholas/powershell/regex a.log/
posh>
library:
function SearchFile($dir,$file)
{
"dir is $dir"
"file is $file"
$full = [string]::Concat("full is ",$dir,"/",$file)
$full
#$pattern='(?=.*?foo)(?=.*?bar)'
#$string = Get-Content $full
#$result = $string | Select-String $pattern
#$result
}
worker:
. /home/nicholas/powershell/functions/library.ps1
$dir = "/home/nicholas/powershell/regex"
$file = "a.log"
SearchFile($dir,$file)
I seem to be passing an array of sorts for $dir and nothing is getting assigned for $file in SearchFile as expected.

Can be done in a simpler way :
function SearchFile ($var_1, $var_2) {
$full_path = "$var_1/$var_2"
$full_path # Output --> C:/temp/test.txt
}
$my_dir = "C:/temp"
$my_file = "test.txt"
SearchFile $my_dir $my_file # Do not use coma when calling a Function

Related

How can I reach the last zip in a long line of nested zips?

I have a task to reach the last file in long line of nested zip archives. They go like this:
3301.zip
| 3300.zip
| 3299.zip
|
...
| 1.zip
Basically, I have to extract one archive from another 3300 times in order to reach the file within 1.zip.
I have searched for ways to do this, but maybe my search terms weren't right or I missed something. I tried "reach last file nested zips", "extract nested zips". My working environment is Linux and I tried several Terminal commands and tools. Nothing did what I wanted.
Here is a Perl script, nested-unzip that walks through nested zip files and prints the contents if the innermost zip file.
#!/usr/bin/perl
use strict;
use warnings;
use Archive::Zip::SimpleZip qw($SimpleZipError) ;
use File::Basename;
use Text::Glob;
sub walk
{
my $zip = shift;
my $path = shift ;
my $depth = shift // 1 ;
my $indent = ' ' x $depth;
for my $p (<$path/*>)
{
my $filename = basename $p;
my $dir = dirname $p;
if (-d $p)
{
print $indent . "$filename [as $filename.zip]\n";
my $newfh = $zip->openMember(Name => $filename . ".zip");
my $newzip = new Archive::Zip::SimpleZip $newfh, Stream => 1
or die "Cannot create zip file '$filename.zip': $SimpleZipError\n" ;
walk($newzip, $p, $depth + 1);
$newzip->close();
}
else
{
print $indent . "$filename\n";
$zip->add($p, Name => $filename);
}
}
}
my $zipfile = $ARGV[0];
my $path = $ARGV[1] ;
my $zip = new Archive::Zip::SimpleZip $zipfile
or die "Cannot create zip file '$zipfile': $SimpleZipError\n" ;
print "$path\n";
walk($zip, $path);
create a nested zip file to play with
$ echo hello >hello.txt
$ zip 1.zip hello.txt
$ zip 2.zip 1.zip
$ zip 3.zip 2.zip
and finally running the script
$ perl nested-unzip 3.zip
3.zip
2.zip
1.zip
hello.txt
If the zip files are all sequentially numbered, then you can unpack them all with a simple one-liner:
for i in {3301..1} ; do f="$i.zip" ; unzip -q "$f" ; rm "$f" ; done
And should you ever need it, the packing can be done with a very similar one-liner:
f="flag.txt" ; for i in {1..3301} ; do g="$i.zip" ; zip -q $g $f ; rm $f ; f="$g" ; done

Echo statement giving empty output

i have the following Code, but it is giving empty output for the echo statement "echo $dirname" when i type in the same command in CLI it is showing correct output but while running as script giving empty output .
for folderpath in `find /u01/app/SrcFiles/commercial/ngdw/* -name "IQ*"`;
do
folder_count=`ls -d $folderpath/* | wc -l`
echo -e "Total Date folder created : $folder_count in $folderpath \n"
if [ $folder_count -ne 0 ];
then
for dirpath in `find $folderpath/* -name "2*" `;
do
dirname=${dirpath##*/}
(( dirname <= 20210106 )) || continue
echo $dirname
done
fi
done

Replace string by another at specific line number in txt file - Powershell

I saw some post already to do this but I didn't make it work. I would like to replace a string by an other at a specific line number in txt/csv file.
I have one file (that is supposed to update the second one with the new date)
"field1","date1","date2"
****,23/01/2018,03/04/2018
****,22/01/2018,03/04/2018
The second one (that is supposed to be older) :
"field1","date1","date2"
****,20/01/2018,03/04/2018
****,20/01/2018,03/04/2018
My script do the following :
Ask the user for a file to use to update the second asked file.So if there is a line match between some fields of the two files, I would like to update the "date1" by the "date1" of the first file.
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
function Select-FileDialog
{
param([string]$Title,[string]$Directory,[string]$Filter="CSV File (*.csv)|*.csv")
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
$objForm = New-Object System.Windows.Forms.OpenFileDialog
$objForm.InitialDirectory = $Directory
$objForm.Filter = $Filter
$objForm.Title = $Title
$Show = $objForm.ShowDialog()
If ($Show -eq "OK")
{
Return $objForm.FileName
}
Else
{
Write-Error "Operation cancelled by user."
}
}
##Définition des variables
$ErrorActionPreference = "SilentlyContinue"
$dir = split-path -parent $MyInvocation.MyCommand.Definition
$base_file = Select-FileDialog -Title "Select a file" -Directory "$dir"
$bkp_file = "$dir\base.csv.bak"
##Make a backup of initial file
Copy-Item -Path "$final_file" -Destination "$bkp_file"
$final_file = Select-FileDialog -Title "Select a file" -Directory "$dir"
$import = Import-csv $base_file -Delimiter ";"
$tmpFile = "$dir\lineNumberOfMatches.txt"
$tmpFile2 = "$dir\newDates.txt"
foreach ($item in $import){
$source_base = $item.SOURCE
$pays_base = $item.PAYS
$symbo_base = $item.'SYMBO RZO'
$freq_base = $item.FREQUENCE
$periode_base = $item.PERIODE
$affectation_base = $item.AFFECTATION
$rang_base = $item.RANG
$indic_base = $item.INDICATIF
$ancienneSymbo_base = $item.'ANCIENNE SYMBO'
$modulation_base = $item.MODULATION
$datePerception_base = $item.'DATE PERCEPTION'
$dateMAJ_base = $item.'DATE MAJ'
$string = "$source_base;$pays_base;$symbo_base;$freq_base;$periode_base;$affectation_base;$rang_base;$indic_base;$ancienneSymbo_base;$modulation_base"
$match = Get-Content $final_file | Select-String -SimpleMatch "$string"
$new_date = $datePerception_base
echo $match.LineNumber >> $tmpFile #On met les lignes qui matchent et donc à remplacer dans le fichier de base pour changer la valeur plus tard
echo $new_date >> $tmpFile2
}
$i=0
##That's here that I need help
foreach ($line in Get-Content $tmpFile |sort -Unique){
$lineNumber = $line -1
$lineToChange = Get-Content $final_file | Select -Index ($lineNumber)
$old_date = echo $lineToChange | %{ $_.Split(';')[10]; }
$date = Get-Content $tmpFile2 | Select -Index $i
## I have the good results but can't place it at the right line number or overwrite the line
$lineToChange -replace "$old_date", "$date"
$i++
}
rm $tmpFile
rm $tmpFile2
It drives me crazy because I know with shell and sed the problem would be already solved... Thanks for reading and sorry for the long post !
PS : Don't look at the first import, I just take each field of the base file and put it in a variable to concatenate and make my string match with the other file
I finally succeed. I hope it could help someone...
##That's here that I need help
foreach ($line in Get-Content $tmpFile |sort -Unique){
$lineNumber = $line -1
$lineToChange = Get-Content $final_file | Select -Index ($lineNumber)
$old_date = echo $lineToChange | %{ $_.Split(';')[10]; }
$date = Get-Content $tmpFile2 | Select -Index $i
## I have the good results but can't place it at the right line number or overwrite the line
$lineToChange -replace "$old_date", "$date"
$i++
}
Replaced by :
$i=0
foreach ($line in Get-Content $tmpFile |sort -Unique){
$content = Get-Content $final_file
$lineNumber = $line -1
$lineToChange = Get-Content $final_file | Select -Index ($lineNumber)
#echo $lineToChange
$old_date = echo $lineToChange | %{ $_.Split(';')[10]; }
$date = Get-Content $tmpFile2 | Select -Index $i
$new_line = $lineToChange -replace "$old_date", "$date"
echo $new_line
for ($y = 0; $y -le ($content.Length -1); $y++){
if ($y -eq $lineNumber){
$content[$y] = $new_line
Set-Content $final_file $content
}
}
$i++
}

recursion issue in shell script

function syncfile(){
echo "[ DONE $file ]"
return ;
}
function syncfolder(){
folder=$1
for foo in `ls -1 $folder`
do
file="$folder/$foo"
if [ -d $file ];then
syncfolder $file
elif [ -e $file ];then
syncfile $file
else
echo "$file is neither file nor directory"
fi
done
return;
}
above are my two functions for recursions.. when I call syncfolder $foldername it is not giving proper output in following case ..
suppose hierarchy is like below
portchanges/
portchanges/script/script1/script1.sh
portchanges/script/script1/script2.sh
portchanges/script/script1/script3.sh
portchanges/script/script4.sh
portchanges/script/script5.sh
portchanges/script6.sh
portchanges/script7.sh
portchanges/appl/script11/script11.sh
portchanges/appl/script11/script12.sh
portchanges/appl/script11/script13.sh
now if foldername=portchanges
and I call syncfolder $foldername
It process only for
portchanges/script/script1/script1.sh
portchanges/script/script1/script2.sh
portchanges/script/script1/script3.sh
with function syncfile() function call...and then it goes to return of syncfolder function.
it is going to search script6.sh and script7.sh in portchanges/script/script1/ directory !! which is totally improper behavior !!
What should I do so It process recursively for entire folder and for every file goes to syncfile() function ?
Declare the folder variable as local. You do not want the recursive call to change the value of the caller's variables.
The following is working in my case. if you want to print the directory name, pass it to syncfile.
function syncfolder(){
syncfile $1
local folder=$1
for foo in `ls -1 $folder`
do
file="$folder/$foo"
if [ -d $file ];then
syncfolder $file
elif [ -e $file ];then
syncfile $file
else
echo "$file is neither file nor directory"
fi
done
return;
}

How to use the case statement to call functions?

Hi I have used this code to find the .java file from the given path and generate the list of the .java files from the path to output file,and count total number of tabs and spaces in each java file.now i need to write the two while loops in function and call that function in case statement, how to do this?
Code:
#!/bin/sh
#
output=/home/user/Desktop/file-list.txt
path=/home/user/Desktop
find $path -type f -name \*.java > $output
echo "Generating files list..."
echo "Done"
while IFS= read file
do
if [ -f "$file" ]; then
spaces=$(tr -cd '\s' < "$file" | wc -c);
echo "$spaces spaces in file $file" >> "/home/user/Desktop/space-count.txt"
fi
done < "$output"
echo "Space Count Done!"
while IFS= read file
do
if [ -f "$file" ]; then
tabs=$(tr -cd '\t' < "$file" | wc -c);
echo "$tabs tabs in file $file" >> "/home/user/Desktop/tab-count.txt"
fi
done < "$output"
echo "Tab Count Done!"
Here is an example of case, but the name of the character could be passed to the function
thereby eliminating the need to case the char.
function count_char
{
flist=$1
ch=$2
case $ch in
" ") chName=space;;
"\t") chName=tab;;
esac
while IFS= read file
do
if [ -f "$file" ]; then
tot=$(tr -cd $ch < "$file" | wc -c);
echo "$tot $chName in file $file" >> "/home/user/Desktop/tab-count.txt"
fi
done < "$flist"
}
# setup code, find command here
# ....
count_char $output " "
count_char $output "\t"

Resources