The problem is that my app tries to add a line to an existing xml file in /system/csc.
I need a function to check if inside the file there is X line and if it is in there the line shouldn't be added also it has to put the line before another line that is present in the file.
You can check whether the line already exist with grep and use sed to insert it if not:
grep -Fxq "foobar line" file || sed -i '/^context line$/i foobar line' file
This will insert the line foobar line before the line context line if foobar line isn't already found in the file.
Alternately you could do it all with sed:
sed -i '/^foobar line$/d;/^context line$/i foobar line' file
try
grep -F "$yourLine" file.xml
awk sum up multiple files show lines which does not appear on both sets of files
check my answer on this page (the last answer to my own question) I am using ed and after finding the line that the entry needs to be added to I use typical vi commands to add the entry after the line number.
You can use the same script after doing a grep for string in your file if not
grep pattern $file > /dev/null
if [ $? = 0 ]; then
echo "found"
else
run_ed_function
fi
To check if string equals ENTIRE LINE
FILE="./myfile"
STRING="myString"
if grep -x ^$STRING.$ $FILE; then
echo 'Found'
else
echo 'Not Found'
fi
In that case, the code would match 'myString' but not 'Hello myString'
Related
I need to calculate md5 hash of files in a directory hierarchy. I am using the following case as a test. The Android device I have has a md5 binary, but needs absolute path of file (md5 <filename>).
I have the following directory hierarchy on a Android device:
/data/local/tmp/test1
/data/local/tmp/test1/test2
/data/local/tmp/test1/test2/test3
To get list of absolute paths, I followed the answer mentioned here.
$ adb shell 'function rcrls() { ls -d $1/* | while read f; do echo "$f"; if [ -d "$f" ]; then rcrls "$f"; fi; done } ; rcrls /data/local/tmp/' > filelist.txt
Now I have list of absolute paths of each file.
Next I want to read this file in a script line by line, and call md5 for each line. md5 will print a message if the input is a directory. I followed the example here.
#! /bin/bash
filename='filelist.txt'
cat $filename | while read LINE; do
adb shell 'md5 $LINE'
done
I get the following output:
/data/local/tmp/test1/test2
/data/local/tmp/test1/test2/test3
could not read /data/local/tmp/test1, Is a directory
I expected it to print a directory warning for test1 and test2, and then md5 for test3, as test3 is a file. Can someone suggest how to fix this code ? I was expecting something like:
could not read /data/local/tmp/test1, Is a directory
could not read /data/local/tmp/test1/test2, Is a directory
<hash_value> /data/local/tmp/test1/test2/test3
You should use find:
adb shell find /data/local/tmp -type f -exec md5sum {} '\;'
Sorry if the question is easy. I am kind of a beginner in shell scripting, and I need to write a script which will work on a text file on a machine which mksh installed, but no working version of sed or most gnu utilities or compatible.
There is also no version of dos2unix installed.
The script receives a file which is dos formatted, but is quite simple in the kind of characters it contains (only letters and numbers, lenght of each line below 20 characters, few than 1000 lines), and it reads the file character by character adding the character to a "line" variable. When it reaches a carriage return it prints the line. Usage will be sh script.sh file.txt > newfile.txt.
The script does not work as intended and I am not really sure why:
#!/bin/sh
riga="";
nomefile="$1";
while IFS='' read -r -n1 carattere;
do
if [[ $carattere != *$'\r'* ]]; then
riga="${riga}carattere";
elif [[ $carattere == *$'\r'* ]]; then
print "${riga%$}";
riga="";
fi
done < "$nomefile"
This is the output of the script as originally written:
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
caratterecaratterecaratterecaratterecaratterecaratterecaratterecaratterecarattere
I read the excellent man pages of ksh at https://www.freebsd.org/cgi/man.cgi?query=ksh and modified the script as follows:
#!/bin/sh
#!i=0
#!
riga="";
nomefile="$1";
while IFS='' read -r -n1 carattere;
do
if [[ $carattere != *$'\r'* ]]; then
riga="${riga}$carattere";
elif [[ $carattere == *$'\r'* ]]; then
print "${riga%$}";
riga="";
fi
done < "$nomefile"
The output is similar to what I intend, but blank lines are inserted between printed lines:
ID
1
2
3
4
5
6
7
8
Ok, after more reading of the ksh man pages and some tests, I found out what wasnt working. The first version of my script did not correctly append the characters I read to the riga variable, because I did not use a substitution ($) to append the carattere variable.
The second version worked as intended, but did not take into consideration the fact that dos files terminate lines with CRLF: I was thus checking for the \r character, and this meant the \n character was added to my riga variable. I modified the first if condition to check if the character is different from \n too.
Then an additional problem in my script was that, in the structure of files I want to convert, there are n lines and the last line is not terminated. This means my script would not write the characters of the last line in the riga variable, but it would not print the last line. I solved this adding a print instruction after the while cycle, using the -n parameter to avoid printing a newline after the string.
The final version of the script is:
#!/bin/sh
#!i=0
#!^M
riga="";
nomefile="$1";
while IFS='' read -r -n1 carattere;
do
if [[ $carattere != *$'\r'* ]] && [[ $carattere != *$'\n'* ]]; then
riga="${riga}$carattere";
elif [[ $carattere == *$'\r'* ]]; then
print "${riga%$}";
riga="";
fi
done < "$nomefile"
print -n "${riga%$}";
Thanks to Benjamin whose comments put me in the right direction to solve my problem.
I have two lists
list1:
A:1
B:3
C:1
D:5
list2:
1:blue
3:green
5:red
How can i do for have something like:
Desired output(file3):
A:blue
B:green
C:blue
D:red
And here is my unworking code ...
#!/system/bin/bash
list1=$(cat file1)
list2=$(cat file2)
for i in "$list1"; do
num_file1=$( echo $i | cut -d ":" -f 2)
string_file2=$(cat $list2 | grep "$num_file1" | cut -d ":" -f 2)
echo -e "$i" | sed "s/$num_file1/$string_file2/" > list3
done
I also tried
sed 's/"$num_file1"/"$string_file2"/' and many other but failed every times for what i want .. Where i am wrung with sed ??
Ps: its on android ... and few command are misted ...
Give this awk line a try:
awk -F':' 'NR==FNR{k[$1]=$2;next}{print $1 FS k[$1]}' f2 f1
I didn't test the code, but it should work.
Note this assumes that all idx in file1 we have corresponding entry in file2
The awk solution is perfectly fine. Using lesser commands, you could say:
sort -t \: -k 2 list1 | join -t \: -1 2 - list2 | cut -d \: -f 2,3 | sort -t \:
Where i am wrung with sed ??
You were quite close, wrong only in three places.
for i in "$list1"; do has to be for i in $list1; do without quotes, since you want to process the lines individually, not the whole $list1 at once.
string_file2=$(cat $list2 | …) has to be string_file2=$(echo "$list2" | …) with echo instead of cat (since you already read the file2 into the variable $list2) and with quotes to preserve the line separation.
The output redirection > list3 has to be moved away from the echo -e "$i" | sed … line to the end of the done line, otherwise only the last output line would remain in file3.
Another approach to the problem would be to use an array for the colors, indexed by their number:
#!/bin/bash
eval rgb=($(sed 's/\(.*\):/[\1]=/' <file2)) # change 1:blue to [1]=blue etc.
while IFS=: read letter number
do echo $letter:${rgb[$number]} # change A:1 to A:blue etc.
done <file1 >file3
I was wondering about how to create / extract / verify .tar.md5 files. These files are used when flashing images to android devices, see here for example.
As far as I can tell the checksum is appended to the file like this:
cp file.tar file.tar.md5
md5sum file.tar >> file.tar.md5
Firstly I would like to know how to extract the file. Can I simply use tar -xf on the file.tar.md5?
How can I verify the integrity of the file? I would like to remove the last bytes (containing the checksum) from the file to obtain the original file back. I guess you would have to use a regexp to match the checksum file.tar? Is something like this implemented somewhere already?
First of all tar -xf should work since tar continues while it matches its' packing algorithm. If the file stops matching so would tar.
Also most archive managers such as 7-zip or winrar will open it if you remove the ".md5".
They might print error regarding mismatch with the end of the file, ignore it.
As for verifying the file:
print out the stored md5sum: tail -z -n 1 [File name here].tar.md5
calculate the md5sum of the tar part of the file: head -z -n -1 [File name here].tar.md5 | md5sum
What works for me with Ubuntu 19.10 is:
download single-file 4 GiB zip from sammobile com
unzip to several *.tar.md5
run the below command-line
.
for F in *.tar.md5; do echo -n "$F " &&
EXP=($(tail --lines=1 "$F")) &&
ACT=($(head --lines=-1 "$F" | md5sum)) &&
if [ ${EXP[0]} = ${ACT[0]} ]; then echo -n "md5ok " &&
tar --extract --file "$F" && echo "done"
else echo "FAIL"; fi; done &&
unlz4 --multiple --verbose *.lz4
AP_G965U1UEU3ARL1_CL14745140_QB21029084_REV01_user_low_ship_MULTI_CERT_meta.tar.md5 md5ok done
BL_G965U1UEU3ARL1_CL14745140_QB21029084_REV01_user_low_ship_MULTI_CERT.tar.md5 md5ok done
CP_G965U1UEU3ARL1_CP11407818_CL14745140_QB21029084_REV01_user_low_ship_MULTI_CERT.tar.md5 md5ok done
CSC_OMC_OYM_G965U1OYM3ARL1_CL14745140_QB21029084_REV01_user_low_ship_MULTI_CERT.tar.md5 md5ok done
HOME_CSC_OMC_OYM_G965U1OYM3ARL1_CL14745140_QB21029084_REV01_user_low_ship_MULTI_CERT.tar.md5 md5ok done
…
But we should all try to get away from bash
I have a shell script like this :
sed -i '/^###########/,/^#End of Build.Prop/d' /system/build.prop;
#
sed -i '/^#Start Build.Prop Tweak/,/^#End of Build.Prop Tweak/d' /system/build.prop;
#
sed -i '/^#Start Build.Prop Tweak/,/^ro\.config\.hwfeature_wakeupkey=0/d' /system/build.prop;
Of the three Shell Commands stated above none of them works when put in a sh file. But, if I use a TerminalEmulator, the three scripts can be executed
I want to use the scripts in an Android Device
No, it is too dangerous.
When the end-search tag is missing, you will delete a large part of your file.
When you want to delete the first and second line in a file, it seems working ok:
$ cat test.txt
first line
second line
third line
$ cat test.txt | sed '/first/,/second/ d'
third line
EDIT: One command less with sed '/first/,/second/ d' test.txt
But what happens when the second line can not be found?
Your sed command should skip removing lines, but it will:
$ cat test.txt | sed '/first/,/mistake/ d'
$
EDIT: One command less with sed '/first/,/mistake/ d' test.txt
All lines from the first match have been deleted !