converting txt file to zip file in TCL - base64

i convert zip binary file to base64 txt file using other code. Now I want to convert the base64 txt file back to zip file using below code. but the resultant zip file display error. How can I solve this
proc b64en str {
set bits $str
set tail {}
return [string map {
A 000000 B 000001 C 000010 D 000011 E 000100 F 000101
G 000110 H 000111 I 001000 J 001001 K 001010 L 001011
M 001100 N 001101 O 001110 P 001111 Q 010000 R 010001
S 010010 T 010011 U 010100 V 010101 W 010110 X 010111
Y 011000 Z 011001 a 011010 b 011011 c 011100 d 011101
e 011110 f 011111 g 100000 h 100001 i 100010 j 100011
k 100100 l 100101 m 100110 n 100111 o 101000 p 101001
q 101010 r 101011 s 101100 t 101101 u 101110 v 101111
w 110000 x 110001 y 110010 z 110011 0 110100 1 110101
2 110110 3 110111 4 111000 5 111001 6 111010 7 111011
8 111100 9 111101 + 111110 / 111111
} $bits]$tail
}
proc callme {file1 file2} {
set file1 [open $file1 r]
set file2 [open $file2 w+]
fconfigure $file2 -translation binary
fconfigure $file1 -buffering line
while {[gets $file1 data]>=0} {
set var $data
set nvar [string trimright $var = ]
set nvar [string trimright $nvar = ]
set var2 [b64en $nvar]
set var3 [binary format B* $var2]
puts $file2 $var3
}
close $file1
close $file2
}
set fp1 [lindex $argv 0]
set fp2 [lindex $argv 1]
callme $fp1 $fp2
The above code is working for txt to txt file
please help me.
Thanks
when in open resultant zip file it display this error

When you're writing binary data, I think you need to specify -nonewline, otherwise you'll have extra newline characters in the binary file, and the data will be corrupt.
puts -nonewline $file2 $var3

Related

Tcl nested loop: wrong # args: should be "for start test next command"

I am trying to do a nested loop, but I'm getting the error message "wrong # args: should be "for start test next command". What does this mean, and could someone please help me find what is wrong with my code?
Note: I'm running the code in Virtual Molecular Dynamics (VMD) so it includes some terms specific to the program like resid and mol. Please disregard those.
#count water molecules between chain A and chain C or between #chain B and chain C
set input_file [open ./name_3_pdb_chain_renamed.dat r]
set data [read $input_file]
set data [split $data "\n"]
close $input_file
set chain_list [lindex $data 0]
cd 7_count_water
set outfile [open count_water3.dat w]
set chain_compare ""
set pdblen [llength $chain_list]
for {set i 0} {$i<$pdblen} {incr i}
{
set pid [lindex [lindex $chain_list $i] 0]
set len [llength [lindex $chain_list $i]]
mol load pdb ../2_chain_rename/${pid}_chain_revised.pdb
mol modstyle 0 top NewCartoon
if {$len==4} {
set chain_compare [lappend chain_compare $pid]
}
set 11 [atomselect top all]
set mid [$11 molid]
mol delete $mid
}
set lll [llength $chain_compare]
for {set j 0} {$j< $lll} {incr j}
{
set pid [lindex $chain_compare $j]
mol load pdb ../2_chain_rename/${pid}_chain_revised.pdb
set 11 [atomselect top "chain A and name CA"]
set res_len [llength [$11 get resid]]
set res_id [$11 get resid]
#residue length for chain C
set ag [atomselect top "chain C and name CA"]
set ag_len [llength [$al get resid]]
set ag_id [$al get resid]
#loop water between chain A and chain C
for {set k 0} {$k<$res_len} {incr k}
{
set water_around_a [atomselect top "{resname HOH and {within 5.0 of {chain A and resid [lindex $res_id $k]} and {within 5.0 of chain C}}} "]
set water_around_a_resid [$water_around_a get resid]
set water_around_a_resname [$water_around_a get resname]
#loop antigen residues around water
for {set g 0} {$g < ag_len} {incr g}
{
set ag_around_water [atomselect top "{chain C and {resid [lindex $res_id $g] and {within 5.0 of $water_around_a}}} "]
set ag_around_water resid [$ag_around_water get resid]
set ag_around_water_resname [$ag_around_water get resname]
puts $outfile "$pid [lindex $res_id $k] [lindex [$11 get resname] $k] $ag_around_water_resname A: $water_around_a_resname"
}
}
set 11 [atomselect top "chain B and name CA"]
set res_len [llength [$b11 get resid]]
set res_id [$b11 get resid]
#residue length for chain C
set ag [atomselect top "chain C and name CA"]
set ag_len [llength [$al get resid]]
set ag_id [$al get resid]
for {set k 0} {$k<$res_len} {incr k}
{
set water_around_b [atomselect top "{resname HOH and {within 5.0 of {chain B and resid [lindex $res_id $k]} and {within 5.0 of chain C}}} "]
set water_around_b_resid [$water_around_b get resid]
set water_around_b_resname [$water_around_b get resname]
#loop antigen residues around water
for {set g 0} {$g < ag_len} {incr g}
{
set ag_around_water [atomselect top "{chain C and {resid [lindex $res_id $g] and {within 5.0 of $water_around_b}}} "]
set ag_around_water resid [$ag_around_water get resid]
set ag_around_water_resname [$ag_around_water get resname]
puts $outfile "$pid [lindex $res_id $k] [lindex [$11 get resname] $k] $ag_around_water_resname A: $water_around_b_resname"
}
}
}
close $outfile
cd ..
You need to start the body of the for loop on the same line. The first curly of the body needs to go after the next command.
for {set i 0} {$i < 10} {incr i} {
puts $i
}

TCL Calculating the length of numbers and formatting properly in text file

I need to work on a text file with 3 columns of value like this:
10 650 8456
1 3264 64643
...
Now i have the following problems:
1) I don't know how counting the length of each numbers (example: 10 = 2 numbers; 650 -> 3 numbers; 64643 -> 5 numbers)
2) Once resolved first point, i need to create an output txt file with a proper data format like this:
|--01--||--02--||--03--|
For each columns there are 8 space useful to write on numbers; if a numbers, for example, has 4 value like 8456, i want to count
other 4 spaces (8 - 4) remaing and then at the 9th space write on second column, another number and so on..
Here an example of the desire output:
|--01--||--02--||--03--|
10 650 8456
1 3264 64643
This is a piece of my code but i don't know how to count numbers and writing after the first numbers the others.
set FileOutput [open $Output w]
set FileInput [open $filename r]
set filecontent [read $FileInput]
set inputList [split $filecontent "\n"]
puts $FileOutputGas " [lindex $inputList 3] [lindex $inputList 4] [lindex $inputList 5]"
but in this way i maintain always the same text format with fixed spaces between numbers; on the contrary i would like to put spaces dynamically.
EDIT: wrong output in this way:
set formatStr {%-8d}
puts $FileOutputGas "[format $formatStr [lindex $num 3]]"
It prints out the format "-8d" and not the number
EDIT 2: Problem with output when bind a button.
The problem i was mentioned before was due to the push of a button. I don't know why the output is correct if i run your script, but if i insert all that action in a button it gives me a wrong output in this way:
button .bCreate -text "CREATE OUTPUT" -width 30 -height 5 -activebackground green -font " -12"
bind .bCreateGas <1> {
set Output "output.txt"
set filename "input.txt"
set FileOutput [open $Output w]
set FileInput [open $filename r]
set filecontent [read $FileInput]
set inputList [split $filecontent "\n"]
set CtriaFind [lsearch -all -inline $inputList CTRIA3*]
foreach line $CtriaFind {
# Extracting all the numbers in a line
set numbers [ regexp -inline -all {\d+} $line ]
set num3 [lindex $numbers 3]
set num4 [lindex $numbers 4]
# Printing each numbers into the file
puts -nonewline $FileOutput " [ format "%-8d" $num3] [ format "%-8d" $num4]"
puts $FileOutput "";
}
}
a part of input.txt file is this one:
GRID 48588 -.366712-3.443-2.3697197
GRID 48606 -.366683-.0373640.374481
GRID 48607 -.366536-3.888-2.3767999
GRID 48608 -.366735-3.589-2.3721335
$$
$$ SPOINT Data
$$
CTRIA3 101268 0 9793 4098 9938
CTRIA3 101353 0 3986 9928 3803
CTRIA3 101363 0 4010 12337 3932
i want to print only
9793 4098
3986 9928
4010 12337
You need to make use of format command to format the display and regexp to retrieve the numbers in each line.
set Output "output.txt"
set filename "input.txt"
set FileOutput [open $Output w]
set FileInput [open $filename r]
set filecontent [read $FileInput]
set inputList [split $filecontent "\n"]
#puts $inputList
foreach line $inputList {
# Extracting all the numbers in a line
set numbers [ regexp -inline -all {\d+} $line ]
# Printing each numbers into the file
foreach num $numbers {
puts -nonewline $FileOutput "[ format "%-8d" $num ]"
}
puts $FileOutput ""; # This is just for the newline character
}
close $filename
close $FileOutput
The - used in the format command specifies that the converted argument should be left-justified in its field. The numbers 8 specifies the width of each field.
Reference : format
Update 1 :
There can be many ways. We have the whole list of numbers in a particular line in the list numbers. Afterwards we are iterating through the list with foreach. Here, instead of looping for all the elements, you can take only the 2nd element using [lindex $numbers 1].
Or, since we know that the elements are separated with spaces, instead of using these ways, we can directly assign it to one list and extract the second element from it. It all depends on your requirement only.

How to add a single special character randomly anywhere inside a string? Bash

I have this script that generates a random character between 8-16. I am confused as to how I would add a single random special character from a bank [! # # $ % ^ & * ( ) _ + ] anywhere randomly inside this string?
if [ $# -eq 0 ] then
pwdlen=$(((RANDOM % 9 ) +8))
spclen=$((RANDOM % 1))
char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V X W Y Z)
chars=(~ ! # # $ % ^ & * - +)
#rand2=$random % 11
max=${#char[*]}
for i in `seq 1 $pwdlen`
do
let "rand=$RANDOM % $max"
str="${str}${char[$rand]}"
done
echo $str
exit 0
fi
teststring=foobarspam
specialchars='!##$%^&*()_+'
randomchar=${specialchars:RANDOM % ${#specialchars}:1}
randompos=$(( RANDOM % ( ${#teststring} + 1 ) ))
newstring=${teststring:0:randompos}${randomchar}${teststring:randompos}
You can use the following code.
#!/bin/bash
if [ $# -eq 0 ]; then
pwdlen=$(((RANDOM % 9 ) +8))
spclen=$((RANDOM % 1))
char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V X W Y Z)
chars=('~' '!' '#' '#' '$' '%' '^' '&' '*' '-' '+')
#rand2=$random % 11
max=${#char[*]}
for i in `seq 1 $pwdlen`
do
let "rand=$RANDOM % $max"
str="${str}${char[$rand]}"
done
A=$(echo $str|wc -c) ## To get the count of
P=$((RANDOM % $A)) ## To get a random position of where to insert the character.
I=$((RANDOM % 11)) ## To get a random index number of chars array
C=${chars[$#]}
echo $str | sed 's!^\(.\{'$P'\}\).!\1\'"$C"'!' ## Inserting the special character to string in defined position
exit 0
fi
Output:
$ for i in `seq 1 10`;do ./test1;done
j^eh8BmD2H
0B01^1AN6EVw
Wu2$LLTILuDN8fSV
e^90gmHjksDo
eB7wa\#fmwf
NVAtJkmfqx~
JaHvD%uyO3rB
ncFrgyyz~UkZ
q0LLRHUNATM8DL
X%ARcXgyC1Do
I am not sure what script language are you using. I wrote a solution for you using PHP. If PHP is not what you are using, you should be able to convert the same logic to other languages and get the same results.
<?php
//This is the original string where you want to add a random character to
$org_string = 'This is My original String';
//calculates the length of the string
$org_length = strlen($org_string);
//find a random position
$pos = rand(0, $org_length-1);
//concatenate the first part of the string, random character, the remaining string
$final = substr($org_string, 0, $pos) . getOne() . substr($org_string, $pos);
//print the final value
echo $final;
//return a random string
function getOne(){
//the following string is 12 characters in length. it is all available characters that you want to select from
$str = '!##$%^&*()_+';
//return a random character
return $str[rand(0, 11)];
}
?>

while loop variable reading issue

I have a text file a.txt like this:
1 1 a
2 b
4 4 d
Now I read that text file and feed it into a while loop:
cat a.txt | while read k l o
do
echo " ${k} ${l} ${o} "
if [ "${k}" == "${l}" ]; then
echo " success ; X: ${k} Y : ${l} Z : ${o} "
else
echo " failed ; X: ${k} Y : ${l} Z : ${o} "
fi
done
In my text file 2nd line first value is empty. That's why I'm getting y value in to x and z value in to y.
How can I handle such empty values and get all values printed at their correct positions?
why don't you just insert 0 for empty x value?
anyway you would need 3 values.. /bin/sh read command assigns the first value to the first name..

Could not unlink [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm totally puzzled with unlink() here:
my $file = "\"/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html\"";
unlink($file) or warn "Could not unlink $file: $!";
will throw
Could not unlink "/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html": No such file or directory
while the file actually exists:
$ ls -l "/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html"
-rw-rw-r-- 1 user user 413 Mar 25 13:41 /home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html
EDIT: I also tried:
my $file = "/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html";
my $file = '/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html';
my $file = "\'/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html\'";
Same error.
EDIT2: more tests as required by choroba
Testing the file existence with -f returns false.
Here's a hexdump of the real file name:
$ ls "/home/yasin/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html" | hexdump -c
0000000 / h o m e / y a s i n / D o c u
0000010 m e n t s / P r o g r a m m i n
0000020 g / P e r l / e x t r a c t e d
0000030 / P r u e b a c o n f o r m
0000040 a t e o H T M L / m s g - 2 5
0000050 7 5 - 4 . h t m l \n
000005a
The filename does not contain double quotes. Do not include them in the variable's value.
my $file = '/home/user/Documents/Programming/Perl/extracted/Prueba con formateo HTML/msg-2575-4.html';
unlink $file or warn "Could not unlink $file: $!";
my $file = "\"/home/.../msg-2575-4.html\"";
unlink($file)
is the equivalent of doing
rm "\"/home/.../msg-2575-4.html\""
Obviously, the correct shell command is
rm "/home/.../msg-2575-4.html"
so you want
my $file = "/home/.../msg-2575-4.html";
unlink($file)
or
my $file = '/home/.../msg-2575-4.html';
unlink($file)
If that second rm command works, so does that Perl command.

Resources