Can function get empty arguments? - fish

My code
function foo
argparse -n foo 'u/user=' 'g/group=' 's/shell=' -- $argv
bar $_flag_u $_flag_g $_flag_s
end
function bar -a user group shell
echo $user
echo $group
echo $shell
end
foo $argv
Execute and Result
> fish test.fish -u user_name -g group_name -s shell_name
user_name
group_name
shell_name
> fish test.fish -g group_name -s shell_name
group_name
shell_name
> fish test.fish -u user_name -s shell_name
user_name
shell_name
>
Expectation I want
> fish test.fish -u user_name -g group_name -s shell_name
user_name
group_name
shell_name
> fish test.fish -g group_name -s shell_name
group_name
shell_name
> fish test.fish -u user_name -s shell_name
user_name
shell_name
>
Can I get the expectation?
If -u option is not used, my expectation is that $user in bar function is empty.
(it means that result of "echo $status" is 1 after "set -q user".)
If I have no choice, I'll do bellow:
(Reference: https://github.com/fish-shell/fish-shell/issues/3926)
function foo
argparse -n foo 'u/user=' 'g/group=' 's/shell=' -- $argv
set -q _flag_u; or set _flag_u ''
set -q _flag_g; or set _flag_g ''
set -q _flag_s; or set _flag_s ''
bar $_flag_u $_flag_g $_flag_s
end
function bar -a user group shell
if test -n $user
# do something
end
if test -n $group
# do something
end
if test -n $shell
# do something
end
end
foo $argv

Your issue is this:
function bar -a user group shell
This means bar calls its first argument "user", the second "group" and the third "shell".
When you then run
bar $u $g $s
fish expands the variables. If they are set, they'll expand to as many arguments as they have elements (in fish, all variables are lists!).
So you'll get $u into $user, $g into $group and $s into $shell.
However, if one isn't set (because the option wasn't given in the call to foo), then the variable will expand to nothing, so if e.g. --group wasn't given, this works like
bar $u $s
which will assign the contents of $u to $user and $s to $group - because it is the second argument that bar sees.
To inhibit this, either use set -q or double-quote the variable:
bar "$_flag_u" "$_flag_g" "$_flag_s"

Related

how to insert error returned from copy command from .bat file into table

batch-file:
cd C:\Program Files\pgAdmin 4\v5\runtime
psql -h "Hostname" -p "5432" -U "user_name" -d "dbname" -c "\COPY (SELECT * FROM schema_name.table_name) TO "C:\ExportFromStaging\outputfile.csv" WITH (FORMAT CSV, HEADER TRUE, FORCE_QUOTE *, QUOTE '\"', ESCAPE '''',DELIMITER ';')
Expectation :
If any error occurs in copy command, I want to catch error rerturned from Database eighter in local variable or in table
Example batch file:
cd C:\Program Files\pgAdmin 4\v5\runtime
psql -h "Hostname" -p "5432" -U "user_name" -d "dbname" -c "\COPY (SELECT * FROM schema_name.table_name) TO "C:\ExportFromStaging\outputfile.csv" WITH (FORMAT CSV, HEADER TRUE, FORCE_QUOTE *, QUOTE '\"', ESCAPE '''',DELIMITER ';')
if error
then
insert into error_log (error_message,error_time)
values (#ERRROR_RETURNED_FROM_DATABASE_IFCOPPYING_WENT_WRONG,timestamp);
echo #ERRROR_RETURNED_FROM_DATABASE_IF_COPPYING_WENT_WRONG
```
i don't know postgress but i can hazard a solution. From the psql manual:
psql returns 0 to the shell if it finished normally, 1 if a fatal
error of its own occurs (e.g. out of memory, file not found), 2 if the
connection to the server went bad and the session was not interactive,
and 3 if an error occurred in a script and the variable ON_ERROR_STOP
was set.
you can try:
setlocal EnableDelayedExpansion
rem use double quote if there is space in filename.
cd "C:\Program Files\pgAdmin 4\v5\runtime"
rem psql command.
psql -h "Hostname" -p "5432" -U "user_name" -d "dbname" -c "\COPY (SELECT * FROM schema_name.table_name) TO "C:\ExportFromStaging\outputfile.csv" WITH (FORMAT CSV, HEADER TRUE, FORCE_QUOTE *, QUOTE '\"', ESCAPE '''',DELIMITER ';')
if %ERRORLEVEL% GEQ 1 (
IF %ERRORLEVEL% EQU 1 set "result=psql fatal error."
IF %ERRORLEVEL% EQU 2 set "result=psql connection to the server went bad."
IF %ERRORLEVEL% EQU 3 set "result=psql error occurred in a script: '%ON_ERROR_STOP%'"
echo psql error: [!date! !time!] !result!
:: you can change "timestamp" with variable !date! !time!
:: pseudocode:
:: insert into error_log (error_message,error_time) values ("!result!","!date! !time!");
) else (
IF %ERRORLEVEL% EQU 0 echo psql finished normally.
)

The reason why the script written in centos does not work in crontab

I registered the script to crontab to run every 10 minutes. When I run the script, the log is printed, but if I put it on the cron tab and wait, the log does not appear, so it seems that it does not work. If you have anything I need to add or edit, please let me know :(
my sh script
#!/bin/sh
pslist=`ps -ef | grep ffprobe | awk '{print $2}'`
pscount=`ps -ef | grep ffprobe | wc -l`
logs='/apps/kMobile/kEncoderPy/batch/kill_ffprobe.log'
timestamp=`date +%Y%m%d--%H:%M`
echo "[$timestamp] Kill the Batch process Start :: "$timestamp >> $logs
echo "[$timestamp] process ffprobe running count :: "$pscount >> $logs
for pid in $pslist
do
rtime=`ps -p $pid -o etime | tail -1`
rtime=$rtime | tr -d ' '
minutes=${rtime:6:2}
if [$rtime != "ELAPSED" ]; then
if [ $minutes -gt 10 ]; then
`kill -9 $pid`
echo "[$timestamp] passed 10 minute kill process id : "$pid >> $logs
echo "[$timestamp] process kill after ffprobe running count : "$psount >> $logs
fi
fi
done
my crontab -e
*/10 * * * * /apps/kMobile/batch/kill_ffprobe.sh

Postgres comparing two databases

We running two database servers with around 10 databases and multiple schemas in it (production and test). Every night we restore some of the prod to the test. The backup we do with pg_dump and restore with pg_restore. Now the size of the production and the restored database differnces from a few kb up to 700mb.
Now I want to ensure that the restored data is the same as on the production. I already saw that this is usual to postgres but we have to proof this to our manager. What would be the easiest to proof that the database servers are the same after the restore?
Let me suggest you another approach. You can use pg_restore with single transaction. Quote from de docs:
1
--single-transaction Execute the restore as a single transaction (that is, wrap the emitted commands in BEGIN/COMMIT). This ensures that
either all the commands complete successfully, or no changes are
applied. This option implies --exit-on-error.
In this case you don't need to compare a COUNT on all tables from both sides just because if pg_restore returned 0 (zero) then everything went well.
just solved the provide our solution for the moment.
#!/bin/bash
#
#change to the dir this script is located in (just to be sure)
cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# CONFIGURATION
remoteHost=stackoverflow.com
remotePort=5432
remoteUser=postgres
logfile=00comparsion.txt
#######################
cat "" > $logfile
databases=$(psql -U postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false")
for database in $databases; do
echo ------------------------------------------------------------------------------- >> $logfile
echo $database >> $logfile
echo -------------------------------------------------------------------------------
echo $database
if [ "$(psql -U $remoteUser -h $remoteHost -p $remotePort -tAc "SELECT datname FROM pg_database WHERE datname='$database'" )" = '' ]
then
echo "Database '$database' does not exist on remote host! I quit now!" >> $logfile
exit 3
fi
schemas=$(psql -U postgres -d $database -t -c "SELECT SCHEMA_NAME FROM information_schema.schemata
WHERE SCHEMA_NAME NOT IN ('pg_toast',
'pg_temp_1',
'pg_toast_temp_1',
'pg_catalog',
'information_schema')")
for schema in $schemas; do
echo --$schema >> $logfile
if [ "$(psql -U $remoteUser -h $remoteHost -p $remotePort -tAc "SELECT SCHEMA_NAME FROM information_schema.schemata
WHERE SCHEMA_NAME='$schema'" )" = '' ]
then
echo "Schema '$schema' does not exist on remote host! I quit now!" >> $logfile
exit 3
fi
tables=$(psql -U postgres -d $database -t -c "SELECT TABLE_NAME FROM information_schema.tables
WHERE table_schema = '$schema'")
for table in $tables; do
if [ "$(psql -U $remoteUser -h $remoteHost -p $remotePort -tAc "SELECT TABLE_NAME FROM information_schema.tables
WHERE table_name = '$table'" )" = '' ]
then
echo "table '$table' does not exist on remote host! I quit now!" >> $logfile
exit 3
fi
orderField=$(psql -U postgres -d $database -t -c "SELECT column_name FROM information_schema.columns
WHERE table_schema = '$schema'
AND table_name = '$table' LIMIT 1")
#psql -U postgres -d $database -t -c "SELECT * FROM $table order by $orderField" > l.txt
#fetch same table data on remote instance
#psql -U $remoteUser -h $remoteHost -p $remotePort -d $database -t -c "SELECT * FROM $table order by $orderField" > r.txt
#if !(cmp --print-chars "l.txt" "r.txt")
lcl=$(psql -U postgres -d $database -t -c "SELECT * FROM $table order by $orderField")
rmt=$(psql -U $remoteUser -h $remoteHost -p $remotePort -d $database -t -c "SELECT * FROM $table order by $orderField")
if !("$lcl"="$rmt")
then
echo ---$table ✘ >> $logfile
exit 3
else
echo ---$table ✔ >> $logfile
fi
done
done
done
rm l.txt r.txt
echo ------------------------------------------------------------------------------- >> $logfile
echo comparsion finished, sir! >> $logfile
exit 0

echo -n not working with secondary operation

I have a few filenames in a directory
blabla.01
blabla.02
...
I'm trying to make a new file with the following format:
01 new stuff here
02 more new stuff
...
I wrote a script and dumbed it down a bit:
#!/bin/bash
FILES=$(find . -type f -name "blabla*" | awk -F'[.]' '$(NF-1)>=1' | sort)
for f in $FILES
do
echo -n $f | cut -d "." -f 3
echo "test"
done
the 'test' will be the output of another code..
However in this example i get something like:
01
test02
test
Thanks
Try
printf '%s%s\n' "$(echo "$f" | cut -d . -f3)" "test"
The echo | cut could probably be replaced with something like "${f##*.}" if you always want the laat field.

Powershell variable for cmd argument

I want to use a powershell variable for a cmd argument but I don't know how to make it.
function iptc($file)
{
$newcredit = correspondance($credit)
$cmd = '& C:\exiftool\exiftool.exe -S -t -overwrite_original -Credit=$newcredit $file.FullName'
Invoke-Expression $cmd
}
For example newcredit can be "James" but in my case when I run the command -Credit will only be "$newcredit".
Regards
Single quotes (' ') do not expand variable values in the string. You can address this by either using double quotes (" "):
$cmd = "& C:\exiftool\exiftool.exe -S -t -overwrite_original -Credit=$newcredit $file.FullName"
Or, by the method I most often use, by using string formatting:
$cmd = '& C:\exiftool\exiftool.exe -S -t -overwrite_original -Credit={0} {1}' -f $newcredit, $file.FullName
If either of the parameters has a space in it then the parameter will need to be surrounded by double quotes in the output. In that case I would definitely use string formatting:
$cmd = '& C:\exiftool\exiftool.exe -S -t -overwrite_original -Credit="{0}" "{1}"' -f $newcredit, $file.FullName