Currently I am doing a project and I am stuck. It will be helpful if anyone could help me with it. I am using Linux - Ubuntu system. I using Zenity as my GUI for the book inventory system i am creating. The problem i facing now is i do not know how to transfer the data collected via Zenity --forms to the BookDB.txt .
===================================================================
zenity --forms --title="New book" --text="Add new book" \
--add-entry="Title" \
--add-entry="Author" \
--add-entry="Price" \
--add-entry="Quantity Available" \
--add-entry="Quantity sold"
read title
read author
read price
read QtyA
read QtyS
echo $title:$author:$price:$available:$sold >> BookDB.txt
echo $BookDB "New book title ' $title ' added successfully "
===================================================================
Thanks alot for your help!
zenity outputs to stdout. With a form, the fields are separated, by default, with a pipe. You'll want to do this:
data=$(
zenity --forms --title="New book" --text="Add new book" \
--add-entry="Title" \
--add-entry="Author" \
--add-entry="Price" \
--add-entry="Quantity Available" \
--add-entry="Quantity sold"
)
case $? in
1) echo "you cancelled"; exit 1 ;;
-1) echo "some error occurred"; exit -1 ;;
0) IFS="|" read -r title author price qtyA qtyS <<< "$data" ;;
esac
If you're not comfortable using pipe as the output separator, there's a --separator option. For example, you might want to use the "FS" character: --separator=$'\034', then IFS=$'\034' read -r a b c d e <<<"$data"
I'm finding the documentation for zenity pretty slim, but here's the official manual: https://help.gnome.org/users/zenity/stable/
Related
In Linux/Unix based systems, whenever we execute a command in the shell and we echo the $?, the return value is 0 when its a success and the return value is 1 if the command fails.
So, if I am using the BULK COPY utility called BCP for SQL Server, and if the command fails when there is an error with the source file. For example, if I execute a bcp command like this.
/opt/bin/bcp <tablename> in <source_file> -S -U -P -D
and it says. "0 Rows Copied". It might be due to some errors in the source file. And, after that I do a echo $?. The value returned is still 0.
Is there a way we can capture the return value as 1, when encountered an error?
Thanks.
BCP doesn't document any return value. That's a shortcoming. What you can do is redirect output to a file, and look for error indications (probably, the text "Error").
To add a bit more detail to TT.'s answer, I write the bcp output to another file and then grep through it. My code looks like...
/opt/mssql-tools/bin/bcp "$TABLENAME" in $f \
-S $DEST_IP \
-U $USER -P $PASSWORD \
-d $DEST_DB \
-c \
-t "\t" \
-e $EXPORT_STAGE/$TABLENAME/$TABLENAME.$(basename $f).bcperror.log \
| tee $EXPORT_STAGE/$TABLENAME/$TABLENAME.$(basename $f).bcprun.log
# note here that I preserve the bcp output to can later in script
# look for error messages in the bcp process run itself (manually done since bcp does not throw error codes)
echo -e "\n Checking for error messages in bcp output\n"
if grep -q "Error" $EXPORT_STAGE/$TABLENAME/$TABLENAME.$(basename $f).bcprun.log
then
echo -e "\n\nError: error message detected in bcp process output, exiting..."
exit 255
fi
# can delete since already printing to stdout as well (and can just log the whole thing)
rm -f $EXPORT_STAGE/$TABLENAME/$TABLENAME.$(basename $f).bcprun.log
I have an application that writes files to an external drive formatted as NTFS through the SATA interface.
Before closing the application I make sure that everything is flushed using FlushFileBuffers for each file (i.e. CreateFile, FlushFileBuffers, CloseHandle). Then I remove the drive, without first un-mounting it!
This seems to work fine when plugging the drive back into PC machines. However, when plugging it into a OS X the OS doesn't seem to find any files unless the drive was properly unmounted.
What could be missing from the disk which causes OS X not to find anything and is there a way I can flush that data without having to unmount the drive?
EDIT:
With exfat I have the problem with "dirty" drives not being writable when re-mounted.
You might want to read this Ronag, this might help you:
http://www.yourdailymac.net/2011/06/how-to-read-and-write-ntfs-harddrives-under-mac-os-x/
Snippet...
You might already know that it isn’t possible to read Windows drives that are formatted with the NTFS file structure by default under Mac OS X. The driver that is implemented into OS X is simply not capable of writing to NTFS formatted drives, it is likely that this has something to do with a commercial interest.
It is however quite annoying for a user that wants to exchange files from a Windows NTFS drive. That’s why several commercials applications were developed, but most of them cost money like Paragon NTFS for Mac, but there is also a free and even better solution available.
EDIT - I've read the following, this might aid with remounting NTFS drives etc - I have to admit to only using the MAC every now and again. - hopefully I'm not running off in the wrong direction for you ....
Here's the post I've found on the apple forums -
I have created a script to initialize NTFS HDisks and use them in write mode just by using the native OSX driver, without third party software). It seems to work also under Mavericks. You can download it from:
http://sourceforge.net/projects/native-ntfs-osx/files/
You only need to run it once for each new ntfs disk. Next time you plug a ntfs disk that was alreadyinitialized with my script, the disk will be automatically mounted (however, it will not be displayed in the desktop, you will have to open it from /Volumes).
It is also important that the HD has been safely removed, since NTFS contains a flag to notice if the disk was safely removed or not, not allowing to mount it in write mode with the native OSX driver (something similar happens under Linux). In case it happens you just need to plug it into a windows PC and safely remove the HD (so it cleans that flag).
and for your reference the bash script -
#!/bin/bash
checkExisting(){
echo "Checking if already existing device on file..."
while read fileLine; do
if [ "$line" = "$fileLine" ]; then
echo "[WARNING] Device already initialized on this system. Nothing to do here"
open "$FILENAME"
exit 0;
fi
done < /etc/fstab
}
addLine(){
uuid=$(diskutil info "$FILENAME" | grep UUID | cut -d ':' -f2 | tr -d ' ')
volumeName=$(diskutil info "$FILENAME" | grep "Volume Name" | cut -d ':' -f2 | tr -d ' ')
if [ "$uuid" = "" ]; then
line="LABEL=$volumeName none ntfs rw,auto,nobrowse";
else
line="UUID=$uuid none ntfs rw,auto,nobrowse";
fi
checkExisting;
echo "# New NTFS HD: $volumeName on $(date) " >> /etc/fstab
echo $line >> /etc/fstab
device=$(diskutil info "$FILENAME" | grep "Device Node" | cut -d ':' -f2 | tr -d ' ')
diskutil unmount "$FILENAME"
diskutil mount $device
open $FILENAME;
exit 0;
}
checkDisk(){
filetype=$(diskutil info "$FILENAME" | grep "Type (Bundle):" | cut -d ':' -f2 | tr -d ' ')
#echo $filetype
if [ "$filetype" = "ntfs" ]; then
addLine;
fi
if [ "$filetype" = "" ]; then
echo "Error. Please, select a NTFS device"
fi
}
#Check sudo
if [[ $(/usr/bin/id -u) -ne 0 ]]; then
echo "This script should be run as ROOT. Try sudo"
exit
fi
echo "___________________________________"
echo "RubeniumTB. 2013 --ruben80(at)gmail.com--"
echo ""
echo "Initialize a NTFS Hard Disk on this system to read and write"
echo "Next time you won't need to initialize it again. Just plug and open but"
echo "take into account that:"
echo ""
echo "* Configured disks will not be auto-opened!!"
echo "* You will need to open /Volumes and click on your disk!!"
echo ""
echo "* Although it should not happen anything wrong, use at your own risk"
echo ""
echo "* IMPORTANT!!. Be sure that the NTFS device has been safely removed or it won't"
echo "be mounted in write mode. In this case you can connect it again to any windows PC,"
echo "remove safely, and then connect to your MAC"
echo ""
echo "* Also IMPORTANT!!. To avoid problems use SHORT names for the Volume names, "
echo "NO SPACES, and preferably only letters/numbers. Of course no special characters!!"
echo ""
echo "Now you are ready...."
echo "SELECT a NTFS Disk to initialize on this system"
echo "Write quit to exit"
echo ""
select FILENAME in "/Volumes"/*
do
case "$FILENAME" in
"$QUIT")
echo "Exiting."
break
;;
*)
echo "You picked "$FILENAME" "
checkDisk;
;;
esac
done
I'm tryin to add a text comment (not a note) to a pdf file.
I create a date.ps file with contains the text comment :
%!
/Arial findfont
30 scalefont
setfont
newpath
10 720 moveto
(PAID on 5.1.2013) show
showpage
and I launch the shell command with $i=name of the pdf file to tag:
gs -q -dNOPAUSE -dSAFER -dBATCH -sOutputFile=$RFP/$DOMAINE/$NEWNAME -sDEVICE=pdfwrite -sPAPERSIZE=a4 date.ps $i
This works, but it create a new 1st page empty with the text "PAID on 5.1.2013" alone.
I do not find the trick to overlay the text on the 1st page of the original pdf.
Can you help me pls
You can do this directly to the PDF using the free cpdf command line tools:
For example,
cpdf -add-text "PAID on 5.1.2013" -topleft 100 -font "Helvetica" -font-size 30 in.pdf -o out.pdf
Since cpdf has a strange license for commercial use, I tried to find an alternative. Here is one (you need to install enscript, ps2pdf and (pdftk or qpdf)). The idea is just to use enscript to create a .ps from a text, then you convert this .ps into a .pdf using ps2pdf, and then you stack it on top of the original pdf with pdftk or qpdf...).
pdtfk version:
echo "I will be stamped on top of the page" | \
enscript -B -f Courier-Bold16 -o- | \
ps2pdf - | \
pdftk input.pdf stamp - output output.pdf
qpdf version:
If you want the text to repeat on all pages:
tmpfile=$(mktemp) && echo "I will be stamped on top of the page" | \
enscript -B -f Courier-Bold16 -o- | \
ps2pdf - "$tmpfile" && qpdf input.pdf --overlay "$tmpfile" --repeat=1-z -- output.pdf
if you just want to put it on the first page:
tmpfile=$(mktemp) && echo "I will be stamped on top of the page" | \
enscript -B -f Courier-Bold16 -o- | \
ps2pdf - "$tmpfile" && qpdf input.pdf --overlay "$tmpfile" -- output.pdf
See the enscript documentation for more options on how to format the text.
NB: mktemp is just used to create a temporary file to provide a one-liner solution, since qpdf does not accept input from stdin. Remove the tmpfile with rm "$tmpfile" after the command is done.
Because your PostScript executed a showpage it ejects the first page after marking it, so the remaining content is therefore on the 2nd and subsequent pages. If you don;t execute showpage then the marks you make will be on the first page, and the first PDF page will be drawn 'on top' of it.
More complex code can use BeginPage and EndPage to draw over and under the page contents, and to do so on specified pages, among other things.
[added later]
Try this:
%!
<<
/EndPage
{
0 eq
{
0 eq
{
/Arialabold findfont 22 scalefont setfont newpath 250 820 moveto 1 0 0 setrgbcolor (PAYE PAR CCP LE $DATEPMT) show
} if
true
}
{
pop false
} ifelse
} >> setpagedevice
Works for me.
I have created a .vcf contact with an iPhone and sent the file to myself in email. In that .vcf, I took a photo which is directly saved in the vCard, not in the phone's memory.
In the source of the .vcf, there is a code part starting like this:
PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD/4QBYRXhpZgAATU0AKgAA
And it continues on... Now, I would like to get this photo and save it as a .JPEG. Any ideas how to do that?
Thanks.
In macOS, it easy to to from the line command with "vi" and "base64.
For example,
Export the "Apple Inc." contact that comes with every user account.
Use vi to manually remove the other lines.
Remove the heading and the meta-data for that line
PHOTO;ENCODING=b;TYPE=JPEG:
base64 decode the remaining file
# base64 -D -i Apple\ Inc..vcf -o Apple_Logo.jpeg
The encoding is Base64. You can find a tool for decoding online.
I can recommend Freeformatter.com's decoder, which lets you save as a binary file. You will then need to rename that file to photo.jpg.
You should use a vCard parser (like vpim) that provides the ability to pull photo data from the vCard.
Another vCard parser is ez-vcard, which is written in Java (disclaimer: I am the author).
File file = new File("vcard.vcf");
VCard vcard = Ezvcard.parse(file).first();
for (PhotoType photo : vcard.getPhotos()){
byte data[] = photo.getData();
//save byte array to file
}
Because this isn't https://apple.stackexchange.com/ I'll suggest a quick bash script that I've used to extracted images from .vcf files on the command line:
#!/bin/bash
#vcf_photo_extractor ver 20180207094631 Copyright 2018 alexx, MIT Licence
if [ ! -f "$1" ]; then
echo "Usage: $(basename $0) [path/]any/contact.vcf"
exit 1
fi
DATA=$(cat "$1" |tr -d "\r\n"|sed -e 's/.*TYPE=//' -e 's/END:VCARD.*//')
NAME=$(grep -a '^N;' $1|sed -e 's/.*://')
#if [ $(wc -c <<< $DATA) -lt 5 ];then #bashism
if [ $(echo $DATA|wc -c) -lt 5 ];then
echo "No images found in $1"
exit 2
fi
EXT=${DATA%%:*}
if [ "$EXT" == 'BEGIN' ]; then echo "FAILED to extract $EXT"; exit 3; fi
IMG=${DATA#*:}
FILE=${1%.*}
Fn=${FILE##*/}
if [ -f "${FILE}.${EXT}" ]; then
echo "Overwrite ${FILE}.${EXT} ? "
read -r YN
if [ "$YN" != 'y' ]; then exit; fi
fi
echo $IMG | base64 -id > ${FILE}.${EXT} || \
echo "Failed to output $NAME to ${FILE}.${EXT}"
This script tries to extract the base64 data, decode it using base64 and create an image file. I found on linux that base64 -id worked but base64 -d threw errors.
If you are a fan of single-line code or code-golf then this might work:
cat 1.vcf|tr -d "\n"|sed -e 's/.*TYPE=[^:]*://' -e 's/END:V.*//'|base64 -id >1.jpg
If you want something cleaner then Matt Brock's
vCard_photo_extractor.sh might be what you are looking for.
Used http://www.sobolsoft.com/convertvcfjpg/ with vCards from OSX, with success.
How can I append the following code to the end of numerous php files in a directory and its sub directory:
</div>
<div id="preloader" style="display:none;position: absolute;top: 90px;margin-left: 265px;">
<img src="ajax-loader.gif"/>
</div>
I have tried with:
echo "my text" >> *.php
But the terminal displays the error:
bash : *.php: ambiguous redirect
I usually use tee because I think it looks a little cleaner and it generally fits on one line.
echo "my text" | tee -a *.php
You don't specify the shell, you could try the foreach command. Under tcsh (and I'm sure a very similar version is available for bash) you can say something like interactively:
foreach i (*.php)
foreach> echo "my text" >> $i
foreach> end
$i will take on the name of each file each time through the loop.
As always, when doing operations on a large number of files, it's probably a good idea to test them in a small directory with sample files to make sure it works as expected.
Oops .. bash in error message (I'll tag your question with it). The equivalent loop would be
for i in *.php
do
echo "my text" >> $i
done
If you want to cover multiple directories below the one where you are you can specify
*/*.php
rather than *.php
BashFAQ/056 does a decent job of explaining why what you tried doesn't work. Have a look.
Since you're using bash (according to your error), the for command is your friend.
for filename in *.php; do
echo "text" >> "$filename"
done
If you'd like to pull "text" from a file, you could instead do this:
for filename in *.php; do
cat /path/to/sourcefile >> "$filename"
done
Now ... you might have files in subdirectories. If so, you could use the find command to find and process them:
find . -name "*.php" -type f -exec sh -c "cat /path/to/sourcefile >> {}" \;
The find command identifies what files using conditions like -name and -type, then the -exec command runs basically the same thing I showed you in the previous "for" loop. The final \; indicates to find that this is the end of arguments to the -exec option.
You can man find for lots more details about this.
The find command is portable and is generally recommended for this kind of activity especially if you want your solution to be portable to other systems. But since you're currently using bash, you may also be able to handle subdirectories using bash's globstar option:
shopt -s globstar
for filename in **/*.php; do
cat /path/to/sourcefile >> "$filename"
done
You can man bash and search for "globstar" for more details about this. This option requires bash version 4 or higher.
NOTE: You may have other problems with what you're doing. PHP scripts don't need to end with a ?>, so you might be adding HTML that the script will try to interpret as PHP code.
You can use sed combined with find. Assume your project tree is
/MyProject/
/MyProject/Page1/file.php
/MyProject/Page2/file.php
etc.
Save the code you want to append on /MyProject/. Call it append.txt
From /MyProject/ run:
find . -name "*.php" -print | xargs sed -i '$r append.txt'
Explain:
find does as it is, it looks for all .php, including subdirectories
xargs will pass (i.e. run) sed for all .php that have just been found
sed will do the appending. '$r append.txt' means go to the end of the file ($) and write (paste) whatever is in append.txt there. Don't forget -i otherwise it will just print out the appended file and not save it.
Source: http://www.grymoire.com/unix/Sed.html#uh-37
You can do (Work even if there's space in your file path) :
#!/bin/bash
# Create a tempory file named /tmp/end_of_my_php.txt
cat << EOF > /tmp/end_of_my_php.txt
</div>
<div id="preloader" style="display:none;position: absolute;top: 90px;margin-left: 265px;">
<img src="ajax-loader.gif"/>
</div>
EOF
find . -type f -name "*.php" | while read the_file
do
echo "Processing $the_file"
#cp "$the_file" "${the_file}.bak" # Uncomment if you want to save a backup of your file
cat /tmp/end_of_my_php.txt >> "$the_file"
done
echo
echo done
PS: You must run the script from the directory you want to browse
Inspired from #Dantastic answer :
echo "my text" | tee -a file1.txt | tee -a file2.txt