is it possible to prepend a character to every line of terminal output, for every command? - linux

Is it possible?
For example, say I want to run the command ll:
My output would look something like this:
josh#zeitgeist ~ ll
total 41148
drwxr-xr-x 42 josh josh 4096 Aug 4 22:52 ./
drwxr-xr-x 4 root root 4096 Jul 9 21:18 ../
-rw-rw-r-- 1 josh josh 3523718 Jul 11 00:17 2017-07-11-001710_3840x2160_scrot.png
but I want it to look like this:
josh#zeitgeist ~ ll
XXXtotal 41148
XXXdrwxr-xr-x 42 josh josh 4096 Aug 4 22:52 ./
XXXdrwxr-xr-x 4 root root 4096 Jul 9 21:18 ../
XXX-rw-rw-r-- 1 josh josh 3523718 Jul 11 00:17 2017-07-11-XXX001710_3840x2160_scrot.png
I already know about using PS1='XXX' to change the prompt; is there a way to change every line of the output that gets displayed, specifically in the terminal(not changing the output and putting it in a file)?
I would like to do this to have a unified line of characters going down the left side of my terminal.

You can easily do it with sed:
ll | sed 's/./XXX&/'

Prepend XXXto all lines including empty lines.
ll | sed 's/^/XXX/'
Edit:
After changing your PS1 you can invoke the solution for all commands using
bash | sed 's/^/XXX/'

You could do something like this I suppose:
while read; do echo "xxx $REPLY"; done < <(ls -l)
Not really sure what the purpose of this would be though.

Using awk:
$ ll|awk '$0="XXX"$0'

Related

Copying files with wildcard * why isn't it working?

There are 3 txt files called
1.txt 2.txt 3.txt
I want to batch copy with the name
1.txt.cp 2.txt.cp 3.txt.cp
using the wildcard *
I entered the command cp *.txt *.txt.cp
but it wasn't working...
cp : target *.txt.cp : is not a directory
what was the problem???
Use: for i in *.txt; do cp "$i" "$i.cp"; done
Example:
$ ls -l *.txt
-rw-r--r-- 1 halley halley 20 out 27 08:14 1.txt
-rw-r--r-- 1 halley halley 25 out 27 08:14 2.txt
-rw-r--r-- 1 halley halley 33 out 27 08:15 3.txt
$ ls -l *.cp
ls: could not access '*.cp': File or directory does not exist
$ for i in *.txt; do cp "$i" "$i.cp"; done
$ ls -l *.cp
-rw-r--r-- 1 halley halley 20 out 27 08:32 1.txt.cp
-rw-r--r-- 1 halley halley 25 out 27 08:32 2.txt.cp
-rw-r--r-- 1 halley halley 33 out 27 08:32 3.txt.cp
$ for i in *.txt; do diff "$i" "$i.cp"; done
$
If you are used to MS/Windown CMD shell, it is important to note that Unix system handle very differently the wild cards. MS/Windows has kept the MS/DOS rule that said that wild cards were not interpreted but were passed to the command. The command sees the wildcard characters and can handle the second * in the command as noting where the match from the first should go, making copy ab.* cd.* sensible.
In Unix (and derivatives like Linux) the shell is in charge of handling the wildcards and it replaces any word containing one with all the possible matches. The good news is that the command has not to care about that. But the downside is that if the current folder contains ab.txt ab.md5 cd.jpg, a command copy ab.* cd.* will be translated into copy ab.txt ab.md5 cd.jpg which is probably not want you would expect...
The underlying reason is Unix shells are much more versatile than the good old MS/DOS inherited CMD.EXE and do have simple to use for and if compound commands. Just look at #Halley Oliveira's answer for the syntax for your use case.

How to perform 'sed' operation between start and end time among multiple logs in case of log rollover.?

$ls -lrt test*log*
-rwxr----- 1 root xyzgroup 54231265 Sep 4 16:06 test.log.9
-rwxr----- 1 root xyzgroup 53990979 Sep 4 16:06 test.log.8
-rwxr----- 1 root xyzgroup 53372511 Sep 4 16:06 test.log.7
$cat test.log.9|head -5
Sep 4 12:59:01.701796 <sometext>
Sep 4 12:59:01.701796 <sometext>
Sep 4 12:59:01.720171 <sometext>
Sep 4 12:59:01.720171 <sometext>
Sep 4 12:59:01.720699 <sometext>
$cat test.log.9|tail -5
Sep 4 13:16:01.880489 <sometext>
Sep 4 13:16:01.880489 <sometext>
Sep 4 13:16:01.880489 <sometext>
Sep 4 13:16:01.880489 <sometext>
Sep 4 13:16:01.880489 <sometext>
$cat test.log.8|head -5
Sep 4 13:16:01.898749 <sometext>
Sep 4 13:16:01.898749 <sometext>
Sep 4 13:16:01.898749 <sometext>
Sep 4 13:16:01.898948 <sometext>
Sep 4 13:16:01.898948 <sometext>
$cat test.log.8|tail -5
Sep 4 13:35:02.513804 <sometext>
Sep 4 13:35:02.513804 <sometext>
Sep 4 13:35:02.513804 <sometext>
Sep 4 13:35:02.514136 <sometext>
Sep 4 13:35:02.514136 <sometext>
Log format at the beginning of each line:
Command:
sed -rn '/Sep 4 09:38:*/,/Sep 4 11:23:*/p' test*log* > temp_test.log
Observation:
When performing sed operation on the listed files, required log content between start and end time is not fetched. Instead it will fetch partial log lines or sometime the output file size increases(in GB). Also some time for shorter duration log lines are properly fetched.
Expected:
Log lines between start and end time stamps.
Edit on behalf of the OP after reverting:
When trying the solution in bodo's answer as a remote command using ssh, an error occurs:
local machine$ sudo ssh user#1.2.3.4 "sudo sed -rn '/Sep 4 09:38:*/,/Sep 4 11:23:*/p' $(ls -vr /user/xyz/test*log*)" > temp_test.log
ls: cannot access /user/xyz/test*log*: No such file or directory
If the problem is caused only by the order of the input files as passed to sed you can use the sorting option -v of the ls command (in your specific use case).
-v natural sort of (version) numbers within text
Compare
echo test.log*
echo $(ls -vr test.log*)
In your specific case you can try
sed -rn '/Sep 4 09:38:*/,/Sep 4 11:23:*/p' $(ls -vr test.log*) > temp_test.log
Note: This solution will not work in all cases.
It requires that the file names resulting from the pattern test*log* do not contain any whitespace or special characters. The file names shown in the question fulfill this requirement.
In general, performing word splitting to extract file names from command output is problematic and should be avoided.
Without knowing the contents of the input files it is impossible to check if there are other causes that could lead to the problems described in the question.
Answer for additional question about remote execution:
The command
sudo ssh user#1.2.3.4 "sudo sed -rn '/Sep 4 09:38:*/,/Sep 4 11:23:*/p' $(ls -vr /user/xyz/test*log*)" > temp_test.log
does not work because ls -vr /user/xyz/test*log* is run on the local machine.
You can try quoting to get this part executed on the remote machine, but this can get complicated.
I suggest to create a shell script on the remote machine, e.g. /home/user/logfilter
#!/bin/sh
if [ $# lt 2 ]
then
echo "usage: logfilter from to" >&2
exit 1
fi
from="$1"
to="$2"
sed -rn "/^$from/,/^$to/p" $(ls -vr /user/xyz/test*log*)
and run it like this
sudo ssh user#1.2.3.4 "sudo ./logfilter 'Sep 4 09:38:' 'Sep 4 11:23:'" > temp_test.log
(untested)

sed permission denied on temporary file

With sed I try to replace the value 0.1.233... On the command line there is no problem; however, when putting this command in a shell script, I get an error:
sed: couldn't open temporary file ../project/cas-dp-ap/sedwi3jVw: Permission denied
I don't understand where this temporary sedwi file comes from.
Do you have any idea why I have this temporary file and how I can pass it?
$(sed -i "s/$current_version/$version/" $PATHPROJET$CREATE_PACKAGE/Chart.yaml)
++ sed -i s/0.1.233/0.1.234/ ../project/cas-dp-ap/Chart.yaml
sed: couldn't open temporary file ../project/cas-dp-ap/sedwi3jVw: Permission denied
+ printf 'The version has been updated to : 0.1.234 \n\n \n\n'
The version has been updated to : 0.1.234
+ printf '***********************************'
sed -i is "in-place editing". However "in-place" isn't really. What happens is more like:
create a temporary file
run sed on original file and put changes into temporary file
delete original file
rename temporary file as original
For example, if we look at the inode of an edited file we can see that it is changed after sed has run:
$ echo hello > a
$ ln a b
$ ls -lai a b
19005916 -rw-rw-r-- 2 jhnc jhnc 6 Jan 31 12:25 a
19005916 -rw-rw-r-- 2 jhnc jhnc 6 Jan 31 12:25 b
$ sed -i 's/hello/goodbye/' a
$ ls -lai a b
19005942 -rw-rw-r-- 1 jhnc jhnc 8 Jan 31 12:25 a
19005916 -rw-rw-r-- 1 jhnc jhnc 6 Jan 31 12:25 b
$
This means that your script has to be able to create files in the folder where it is doing the "in-place" edit.
The proper syntax is identical on the command line and in a script. If you used $(...) at the prompt then you would have received the same error.
sed -i "s/$current_version/$version/" "$PATHPROJET$CREATE_PACKAGE/Chart.yaml"
(Notice also the quoting around the file name. Probably your private variables should use lower case.)
The syntax
$(command)
takes the output from command and tries to execute it as a command. Usually you would use this construct -- called a command substitution -- to interpolate the output of a command into a string, like
echo "Today is $(date)"
(though date +"Today is %c" is probably a better way to do that particular thing).

Assignment asking to use grep command, how would I write a command when it is fine with the find command?

My Intro to OS teacher wants me to enter a command that long lists the /etc directory and finds all files modified or created with the size of 4096 bytes.
My answer is simply find /etc -size 4k -ls.
How am I supposed to use the grep command to do this? It seems kind of pointless...
It sure makes no sense but in IT you kind of get used to insane seeming requirements so here is one:
$ ls -l /etc | grep "^-\([^ ]* *\)\{4\}4096 "
-rw-r--r-- 1 root root 4096 Oct 27 2014 wgetrc
^- it's a file (^d for dir etc.)
[^ ]* * field and delimiting space(s)
\(...\)\{4\} four times previous, ie. filesize is in the fifth field
4096 filesize. Notice the trailing space to limit the size exactly to 4096.

how to do arithmetic operations with the size of the files and directory in shell scripting

how to do arithmetic operations with the size of the files and directory when they are in different unites like free space is in MB and the file size is in GB
With one preparatory command I am able to fetch the size of the "/home/abc/def" directory in MB. Its 30GB so getting in KB is not a good idea.
mount fssizeMB
===== =======
/home/abc/def 30002
root#abc:/home/abc/def> ls -lrth
total 7.0G
drwxrwxrwx 3 root root 114 Oct 29 2012 file1
drwxr-xr-x 3 root root 103 Nov 22 2012 file2
-rw-r--r-- 1 root root 114 Jan 25 2013 file3
-rw-r--r-- 1 mtc users 3.8G Jul 22 03:02 file4 <------------------- concerned file
-rw-r--r-- 1 mtc users 3.2G Jul 24 22:26 file5
-rw-r--r-- 1 root root 0 Jan 5 20:30 file6
How to turn below logic in script:
If twice the file size of file4 is < free space of "/home/abc/def " then echo success or else failure.
You could use stat or du -Sh to get the size of file (don't use ls for that in a script).
And to browse the files of a folder :
for i in <direcory>/*; do ...; done
Then, you could use test or [ commands (or [[ if you use Bash) to make a comparison (with -ge, -gt, -lt, -le options as arithmetic operators).
See the manpages of each command to get more information.
this would work with percentages, just to give you an idea, you could modify it to deal with MB or GB and so on.
my advice: doing arithmetic operations in bash is not such a good idea, you should work with programming languages that deal with special variable data type, like float or str and so on. bash is simpler and doesn't work so well with arithmetic operations. sure it does your + and -, but when it comes to percentages and floats... not so well.
try python or perl, or try researching something else. and definitely use, as suggested above, du -sh
#!/usr/bin/env bash
#take df -h and iterate trough percentages
#check to see if file system is full more than 80 %
perc="$(df -h | awk '{print $5}'| sed -e 's/[%/ a-z/A-Z].*//g' )"
#echo $perc
for p in $perc
do
if [ $p -gt 30 ] #change 30 to whatever
then
df -h | grep $p
echo -e "$p Exceeded on `hostname`"
fi
done
Most commands have options to show the size using a specific unit.
The -h flag of ls and df are to produce "human readable" format, which is not suitable for arithmetic calculations, as they can be in inconsistent units.
To get the size of a file, use stat, or even wc -c. It's a bad practice to parse the output of ls -l, so don't use that.
If you can get the size of a file consistently in kilobytes, and the size of free space consistently in bytes, not a problem, you can just multiply the size in bytes with 1024 to be able to make comparisons in consistent units.
The specific commands and flags to use will depend on your operating system and the software installed.

Resources