How do I use the `join` UNIX command? Nothing is ever output - macos

I feel like I'm misunderstanding a very basic part of the join command, because I cannot get it to work (running OS X).
echo "testing" > 1.txt
echo "text" > 2.txt
join 1.txt 2.txt
No output.
Shouldn't it have "testing text" as the result?

You don't have a join because you don't have 'matching fields'. You need something like
echo "1 testing" > 1.txt
echo "1 text" > 2.txt
join 1.txt 2.txt
to create 1 testing text because it 'joins' (or matches) on the 1

For what you're trying to do, use paste, not join:
> echo "testing" > 1.txt
> echo "text" > 2.txt
> paste 1.txt 2.txt
testing text

Related

check the content of the files if they are same

i have many .txt files(namely 1.txt, 2.txt 3.txt ...etc) saved in a directory and I want to check if the content of the files inside the directory are same or not
All files should be compared with other file if the content is same then print yes, if content not same print no
For Example:
1.txt
a
b
c
2.txt
a
b
c
3.txt
1
2
3
expected output when compare two file 1.txt 2.txt
1.txt 2.txt yes
expected output when compare two file 1.txt 3.txt
1.txt 3.txt no
expected output when compare two file 2.txt 3.txt
2.txt 3.txt no
I tried the script
#!/bin/sh
for file in /home/nir/dat/*.txt
do
echo $file
diff $file $file+1
done
But here problem is it doesnot give the output.Please suggest a better solution thanks.
Something like this in bash:
for i in *
do
for j in *
do
if [[ "$i" < "$j" ]]
then
if cmp -s "$i" "$j"
then
echo $i $j equal
else
echo $i $j differ
fi
fi
done
done
Output:
1.txt 2.txt equal
1.txt 3.txt differ
2.txt 3.txt differ
One idea using an array of the filenames, and borrowing jamesbrown's cmp solution:
# load list of files into array flist[]
flist=(*)
# iterate through all combinations; '${#flist[#]}' ==> number of elements in array
for ((i=0; i<${#flist[#]}; i++))
do
for ((j=i+1; j<${#flist[#]}; j++))
do
# default status = "no" (ie, are files the same?)
status=no
# if files are different this generates a return code of 1 (aka true),
# so the follow-on assignment (status=yes) is executed
cmp -s "${flist[${i}]}" "${flist[${j}]}" && status=yes
echo "${flist[${i}]} ${flist[${j}]} ${status}"
done
done
For the 3 files listed in the question this generates:
1.txt 2.txt yes
1.txt 3.txt no
2.txt 3.txt no

How do I pass variables from the script to the files I am generating using cat?

I am not sure if I am asking the question correctly.
This is what I working with:
a=foo
b=bar
cat 1.txt > new1.txt
Contents of 1.txt:
$a
$b
When run this, my new1.txt looks like this:
$a
$b
What I want:
foo
bar
With envsubst:
export a="foo"
export b="bar"
envsubst < 1.txt > new1.txt
Output to new1.txt:
foo
bar
With sed
sed "s/\$a/$a/; s/\$b/$b/" 1.txt > new1.txt

How to concatenate two files and write between them?

I am trying to achieve something like this with bash script:
c.txt:
contents of a.txt
###
contents of b.txt
Basically I want to write a constant string between the contents of two files and save to a new one without modifying the originals.
This was the closest I could get:
echo "###" >> a.txt|cat b.txt >> out.txt
Using - as a filename usually means to use standard input. Thus:
echo 'something' | cat a.txt - b.txt > new.txt
You could do it with three commands:
cat a.txt > out.txt
echo "###" >> out.txt
cat b.txt >> out.txt
And perhaps make a function out of it:
append_hash() { cat $1 > $3; echo "###" >> $3; cat $2 >> $3; }
Usage:
append_hash a.txt b.txt out.txt

How can I merge before move files?

I have some files (few millions) and I keep file list in files.txt like this:
/home/user/1.txt
/home/user/2.txt
/home/user/3.txt
/home/user/4.txt
/home/user/5.txt
I need to move all, but before move I must merge too.
I can move like this:
#!/bin/bash
for files in $(cat files.txt); do
mv $files /home/user/hop/
done
I can merge all with cat * but I need to merge by twos, like this:
1.txt and 2.txt merge --> 1.txt and move.
3.txt and 4.txt merge --> 3.txt and move.
5.txt --> 5.txt and move.
But I must merge before move, in /home/user/, not in /home/user/hop/
How can I do this?
You can use $ cat file1 file2 file3 file4 file5 file6 > out.txt after you moved them, with this you can also set the order of the files to be merged.
Also works for binaries.
You can use this script:
while read -r f; do
if ((++i % 2)); then
p="$f"
else
cat "$f" >> "$p"
mv "$p" /home/user/hop/
rm "$f"
unset p
fi
done < list.txt
[[ -n $p ]] && mv "$p" /home/user/hop/

Opening a file in write mode

I have a file called a.txt. with values like
1
2
3
...
I want to overwrite this file but
echo "$var" >> a.txt
echo "$var1" >> a.txt
echo "$var2" >> a.txt
...
just appends. Using > is not useful as well. How can i overwrite with using >> operator in shell script?
You may want to use > for the first redirection and >> for subsequent redirections:
echo "$var" > a.txt
echo "$var1" >> a.txt
echo "$var2" >> a.txt
> truncates the file if it exists, and would do what you originally asked.
>> appends to the file if it exists.
If you want to overwrite the content of a file (not truncate it), use 1<>
e.g.:
[23:58:27 0 ~/tmp] $ echo foobar >a
[23:58:28 0 ~/tmp] $ cat a
foobar
[23:58:50 0 ~/tmp] $ echo -n bar 1<>a
[23:58:53 0 ~/tmp] $ cat a
barbar
In what way is using > not useful? That explicitly does what you want by overwriting the file, so use > for the first and then >> to append future values.
echo "$var
$var1
$var2" > a.txt
or
echo -e "$var\n$var1\n$var2" > a.txt

Resources