combine output of pipes - bash

Let's say I run a command in Bash like:
ls -l | grep filename
How can I save output of both command to a variable? In another words output of "ls -l" and "grep filename" to the same variable?
The command must use a pipe.
Thank you in advance!
combinedOutput = ""
ls -l
total 4
-rw-r--r-- 1 webmaster webmaster 0 Nov 16 20:34 a
-rw-r--r-- 1 webmaster webmaster 0 Nov 16 20:34 b
-rw-r--r-- 1 webmaster webmaster 0 Nov 16 20:34 file1.txt
-rw-r--r-- 1 webmaster webmaster 0 Nov 16 20:34 file2.txt
-rw-r--r-- 1 webmaster webmaster 5 Nov 16 20:34 main.sh
ls -l | grep main.sh
-rw-r--r-- 1 webmaster webmaster 20 Nov 16 20:35 main.sh
echo $combinedOutput
total 4
-rw-r--r-- 1 webmaster webmaster 0 Nov 16 20:34 a
-rw-r--r-- 1 webmaster webmaster 0 Nov 16 20:34 b
-rw-r--r-- 1 webmaster webmaster 0 Nov 16 20:34 file1.txt
-rw-r--r-- 1 webmaster webmaster 0 Nov 16 20:34 file2.txt
-rw-r--r-- 1 webmaster webmaster 5 Nov 16 20:34 main.sh
-rw-r--r-- 1 webmaster webmaster 20 Nov 16 20:35 main.sh
UPDATE #1:
A better example: let's say I am trying to archive and compress a directory using the following command:
tar cvf - /some/directory/ | pigz --verbose -1 -p 4 >compressed_archive.tgz;
The question is how to put outputs of "tar cvf - /some/directory/" and "pigz --verbose -1 -p 4 >compressed_archive.tgz" to a variable.

Simply:
combinedOutput=$(( ls -l | tee /dev/stderr | grep filename ) 2>&1)
echo "$combinedOutput"

Just run two commands.
combinedOutput=$(
ls -l
ls -l | grep filename
)
But anyway, you may be more comfortable with just:
one=$(ls -l)
two=$(ls -l | grep filename)
combinedOutput="$one
$two"
It's not possible to get the output you want with echo $combinedOutput. You can do echo "$combinedOutput". Consider researching shell quoting. Check your scripts with shellcheck.

Related

Retrieving the last modified file in a directory over FTP using a shell script with curl

I am getting pulling the data from server and placing that in my local.
curl --verbose --ftp-ssl--user 'username:password' ftp://abc.com:001//this/is/stackoverflow/ > /home/dir1/dir2/dir3
In ideal scenario i am getting below output after hitting more dir3 command in unix.
drwxrwxrwx 1 owner group 0 Jan 1 2021 00:00 filename1
drwxrwxrwx 1 owner group 0 Jan 1 2022 04:30 filename2
drwxrwxrwx 1 owner group 0 Jan 1 2021 06:30 filename3
-rwxrwxrwx 1 owner group 1122 Jan 1 2022 08:30 filename4
-rwxrwxrwx 1 owner group 2233 Jan 1 2022 10:30 filename5
-rwxrwxrwx 1 owner group 3344 Jan 1 2023 11:30 filename6
I want something that the date will be in reverse order. I have tried multiple command below,it didnt work. Was trying to reverse with Month as its 6th col so using -k6M
curl --verbose --ftp-ssl--user 'username:password' ftp://abc.com:001//this/is/stackoverflow/ > /home/dir1/dir2/dir3 | sort -n -t- -k6M | tail -1
curl --verbose --ftp-ssl--user 'username:password' ftp://abc.com:001//this/is/stackoverflow/ > /home/dir1/dir2/dir3 | sort -n -t- -k6M
curl --verbose --ftp-ssl--user 'username:password' ftp://abc.com:001//this/is/stackoverflow/ > /home/dir1/dir2/dir3 | sort -k6M | tail -1
some more command i have used. All i want while using curl command , all the files should placed in reverse order in directory itself.

Terminal Piping and Writing to File

I am trying to copy the first two items in my 'Downloads' directory using only the terminal.
I open up zsh, cd into my 'Downloads' directory and start typing.
The below reflects what is shown in the terminal:
% ls -lt | head -3
file1.csv
file2.csv (exactly the files I want)
% ls -lt | head -3 > ToBeCopied.txt
% vim ToBeCopied.txt
total 24625744
-rw-r--r-- 1 Aaron staff 0 22 Apr 15:28 ToBeCopied.txt
-rw-r--r--# 1 Aaron staff 42042 22 Apr 15:16 file1.csv
What happened to file2.csv?

How to pipe output to stdout and variable? [duplicate]

This question already has answers here:
How to store the output of a command in a variable at the same time as printing the output?
(4 answers)
Closed 2 years ago.
When I run the following script, output of ls -la is stored to variable $output.
#! /bin/sh
output=$(ls -la)
How can I pipe output of ls -la to stdout and $output?
I am asking in the context of running borgbackup which can output for a long time during backups.
I would like to be able to track progress when I manually run script while storing output in $output to send it to sysadmin via email.
Use tee;
output=$(ls -lta | tee /dev/tty)
Another way of doing this is by creating a copy of STDOUT, and again using tee to send the output there;
# Create copy of stdout
exec 3>&1
# Run command
output=$(ls -lta | tee /dev/fd/3)
# Close copy
exec 3>&-
Use tee util and pass it to /dev/tty to print stdout.
box: ~/demo
➜ out=$(ls -la | tee /dev/tty)
total 16
drwxr-xr-x 4 chen staff 128 Feb 15 15:59 .
drwxr-xr-x+ 103 chen staff 3296 Feb 15 15:59 ..
-rw-r--r-- 1 chen staff 141 Sep 1 12:38 docker-compose.yml
-rw-r--r-- 1 chen staff 84 Sep 1 12:31 ubuntu.Dockerfile
box: ~/demo
➜ echo $out
total 16
drwxr-xr-x 4 chen staff 128 Feb 15 15:59 .
drwxr-xr-x+ 103 chen staff 3296 Feb 15 15:59 ..
-rw-r--r-- 1 chen staff 141 Sep 1 12:38 docker-compose.yml
-rw-r--r-- 1 chen staff 84 Sep 1 12:31 ubuntu.Dockerfile

Zsh - MacOS Catalina - automatically remove ansi codes into loop using ls command while keeping colors for a single command

I have a tricky configuration about ls command. Indeed, I am using grc colorifying the results od different terminal commands using iTerm2 into MacOS Catalina. My issue is about ls, I have for the moment into my .zshrc :
function ls { grc -es --colour=auto ls --color -Gh -C -rt "$#" ;}
and when I type |~/Test_data| ls, I get for example :
But the issue occurs when I am using for example a loop command with ls :
|~/Test_data| for i in $(ls); do echo $i | xargs ls -lrt; done
Indeed, I get as results :
ls: cannot access ''$'\033''[0m'$'\033''[01;37m'$'\033''[m'$'\033''[00;37mdata_0.txt'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;37mdata_4.txt'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;36mdata_3.py'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;37mdata_2.dat'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;35mdata_1.png'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;37mdata_1.txt'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;36mdata_0.py'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;36mdata_4.py'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;37mdata_3.dat'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;35mdata_2.png'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;37mdata_2.txt'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;36mdata_1.py'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;37mdata_0.dat'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;37mdata_4.dat'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;35mdata_3.png'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;37mdata_3.txt'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[00;36mdata_2.py'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;37mdata_1.dat'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;35mdata_0.png'$'\033''[0m': No such file or directory
ls: cannot access ''$'\033''[01;37m'$'\033''[m'$'\033''[01;35mdata_4.png'$'\033''[0m': No such file or directory
The results of ls command in for i in $(ls) loop generates ansi codes that cannot be processed by pipe xargs ls -lrt.
A workaround is to write in this case :
|~/Test_data| for i in $(ls --color=never); do echo $i | xargs ls -lrt; done
and I get a "normal" list of files :
~/Test_data| for i in $(ls --color=never); do echo $i | xargs ls -lrt; done
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_0.txt
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_4.txt
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_3.py
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_2.dat
-rw-r--r-- 1 fab staff 0 Apr 28 10:34 data_1.png
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_1.txt
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_0.py
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_4.py
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_3.dat
-rw-r--r-- 1 fab staff 0 Apr 28 10:34 data_2.png
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_2.txt
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_1.py
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_0.dat
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_4.dat
-rw-r--r-- 1 fab staff 0 Apr 28 10:34 data_3.png
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_3.txt
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_2.py
-rw-r--r-- 1 fab staff 0 Apr 28 10:32 data_1.dat
-rw-r--r-- 1 fab staff 0 Apr 28 10:34 data_0.png
-rw-r--r-- 1 fab staff 0 Apr 28 10:34 data_4.png
But I am bored to specify the option --color=never for ls at each time in my Shell scripts.
So I have found another alternative to remove these ansi codes by putting into my ~/.zshrc :
function ls { grc -es --colour=auto ls --color -Gh -C -rt "$#" | gsed -r 's/'$(echo -e "\033")'\[[0-9]{1,2}(;([0-9]{1,2})?)?[mK]//g' ;}
This way, I have not to use --color=never but Now, I loose colorified results of a simple |~| ls commmand.
So, to summarize, I would like to keep, when I type the simple command ls, the colorifying of my first function (function ls { grc -es --colour=auto ls --color -Gh -C -rt "$#" ;}) while being able to use ls into for i in $(ls ...); do ...; done loop of Shell scripts without specifying at each time the option --color=never.
I don't know if it possible to switch between the 2 specifications. For example, maybe I could detect automatically if ls command is included in a for loop of shell script?
Have you tried ?
function ls { local color; [ -t 1 ] && color="--color"; grc -es --colour=auto ls $color -Gh -C -rt "$#" ;}

Why the shell doesn't write the good hour and give me the year?

I'm a little bit confused, i changed my time on one file with the shell command :
touch -t = touch -t 201606012135 trial01
But after the ls -lt, I got this :
-rw-r--r-- 1 CharleyD staff 87 1 jun 2016 trial01
drwxr-xr-x 15 CharleyD staff 510 3 apr 12:57 Hybrid_proj
Why the shell doesn't write the hours like the "Hybrid_proj" directory for the "trial01" ? The trial01 file have the hour : 21:35, so itsn't empty.
Indeed, I search to get this in output :
-rw-r--r-- 1 CharleyD staff 87 1 jun 21:35 trial01
drwxr-xr-x 15 CharleyD staff 510 3 apr 12:57 Hybrid_proj
How I can do this ?
Thx a lot buddies to enlighten my way ! ;)
If a file is not from the current year, ls defaults to showing the year instead of the time. The time is still correctly set, just formatted differently.
To always show the full time, with GNU ls, you can use ls --time-style=long-iso -l:
$ ls --time-style=full-iso -l
total 0
-rw-r--r-- 1 user user 0 2017-04-04 13:20 newfile
-rw-r--r-- 1 user user 0 2016-04-03 12:34 oldfile
With BusyBox ls, you can use -e:
$ busybox ls -e
total 0
-rw-r--r-- 1 user user 0 Tue Apr 4 13:20:42 2017 newfile
-rw-r--r-- 1 user user 0 Sun Apr 3 12:34:00 2016 oldfile
With macOS ls, you can use -lT:
$ ls -lT
total 0
-rw-r--r-- 1 user group 0 Apr 4 13:19:35 2017 myfile
-rw-r--r-- 1 user group 0 Apr 3 12:34:00 2016 oldfile
In each case, you get a long timestamp with the same format for older and newer files.
Use the -T option if your ls supports it.

Resources