cat command in unix shell script - bash

I have 2 lines of code
1) With the following code:
for i in `ls *.properties`; do cat $i; done
I get the error:
cat: file_name.properties: No such file or directory.
2) On the other hand:
for i in *.properties; do cat $i; done
Works fine!
I thought both were the same. Can someone help me understand the difference between the two? Using bash shell.

What does the following command print?
cat -v <<< `ls *.properties`
I guess the problem is, that ls is a strange alias, e.g. something like
ls='ls --color'
Edit: I have seen this before. The alias should be: alias ls='ls --color=auto'

Most probably there is a directory which matches *.properties. Then ls will output the files in this directory without the directory name. Then the cat will not find the given filename.
So please check, whether file_name.properties is in the actual directory or in some subdirectory.
EDIT
To reproduce the problem you can try this:
# cd /tmp
# mkdir foo.properties
# touch foo.properties/file_name.properties
# for i in `ls *.properties`; do cat $i; done
cat: file_name.properties: No such file or directory

Related

why alias won't change directory with ls -latr? [duplicate]

This question already has answers here:
Make a Bash alias that takes a parameter?
(24 answers)
Closed last month.
I'm very interested in why this works this way and if we find a solution that's just a benefit of asking the question.
Using kshell,bash and observed the same results. Below is from GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu).
Below is from terminal.
alias tryme='tb=$1;cd $tb'
pwd
/home/tbink1
tryme /home/tbink1/Documents
pwd
/home/tbink1/Documents
But using below doesn't switch directories.
alias tryme='tb=$1;cd $tb;ls -latr'
pwd
/home/tbink1/Documents
tryme /home/tbink1/Pictures
<file list from /home/tbink1/Pictures>
pwd
/home/tbink1/Documents
Mystery to me why the second alias isn't changing directories. The second alias is what I would like to get working. Thanks for any help you give.
Alias doesn't take arguments. It is replaced.
$ tryme /home/tbink1/Pictures
# tryme is _replaced_ by the alias, literally:
$ tb=$1;cd $tb;ls -latr /home/tbink1/Pictures
# then it's executed
# $1 is empty
+ tb=
# $tb is empty,
+ cd
# and ls lists the directory
+ ls -latr /home/tbink1/Pictures
cd with no arguments changes to home directory. $1 is your shell $1, i.e. bash -s this_is_first_arg:
$ bash -s this_is_first_arg
$ echo $1
this_is_first_arg
$ alias tryme='tb=$1;cd $tb'
$ tryme
bash: cd: this_is_first_arg: No such file or directory
Use a function, not an alias.

Bash: use an alias in a filepath

I cannot seem to figure out how to use an alias for a filename in a path. For example:
alias a="ls /tmp/ -tr | tail -n 1"
cat /tmp/a
The alias gives me the name of the most recent file written in /tmp/. Then I try to cat that file and I get cat: /tmp/a: No such file or directory.
When I just type a I get the right thing, for instance some_log_I_just_wrote_to.log.
Obviously what I want is for cat /tmp/a to be translated into cat /tmp/some_log_I_just_wrote_to.log so that I can see the log.
Any ideas on what the right way to do this is? I sometimes get tangled up in bash with when to use aliases and symlinks and just plain variables, etc.
Thanks!
Create the alias with
alias a='ls /tmp/ -tr | tail -n 1'
Use the alias with cat
cat $(echo -n /tmp/ && a)

Unix Bash Alias Command

I am trying to simplify my work with the help of Alias commands in my bash shell.
Problem Statement:
I want to copy different files from different directories to one single folder. The syntax i am using here is as below
cp <folder>/<file> <path>/file.dir
Here I want to save the destination file with filename.directory for easy identification. To achieve the same, I have written the below alias.
Alias Script
cp $Folder/$fileName ~/<path>/$fileName.$Folder
OR
cp $1/$2 ~/<path>/$2.$1
Expected output,
cp bin/file1 ~/Desktop/personal/file1.bin
cp etc/file2 ~/Desktop/personal/file2.etc*
However, It's failing at parsing the source file. i.e. $Folder is not replaced with my first argument.
cp: cannot stat `/file1': No such file or directory
I am writing the above script only to reduce my command lengths. As I am not expert in the above code, seeking any expert help in resolving the issue.
Rather than using an alias you could use a function which you define in some suitable location such as .profile or .bashrc
For example:
mycp()
{
folder=$1
filename=$2
if [ $# -ne 2 ]
then
echo "Two parameters not entered"
return
fi
if [ -d $folder -a -r $folder/$filename ]
then
cp $folder/$filename ~/playpen/$filename.$folder
else
echo "Invalid parameter"
fi
}
There is no way a bash alias can use arguments as you are trying to do. However, perl based rename can probably help you here. Note that it will effectively mv the files, not cp them.
rename 's|([^/]*)/(.*)|/home/user/path/$2.$1|' */*
Limitations: You can only process the files in 1 sub-directory level.
So, below alias can work (with above limitation):
$ alias backupfiles="rename 's|([^/]*)/(.*)|/home/user/path/\$2.\$1|'"
$ backupfiles */*
You can make more sophisticated perl expression if you want to work with multi-directory-level file structure.
A directory contains some files say ~/Documents/file1.d contains newfile.txt
joe#indiana:~/Documents$ ls -l $file
total 1
-rw-r--r-- 1 joe staff 0 May 5 11:39 newfile.txt
Add the variable 'file' in .bashrc for example my .bashrc is shown here
alias ll='ls -la'
file=~/Documents/file1.d
Now whenever you copy to '$file' it will copy to file1.d directory under ~/Documents :)

Why aren't the BASH commands in for loop working

I have a simple code which is:
#!/bin/bash
#LaTex code generator for figures.
ls *.pdf > pdfs.file
ls *.ps > ps.file
pwd=$(pwd)
for i in {1..2}
do
# var=$(awk 'NR==$i' 'pdfs.file')
echo $pwd
echo $pwd > testfile
done
Why aren't the commands in the for loop working?
The $pwd isnt echoed neither is the testfile created.
I tried these commands without the for loop in a terminal and they work fine.
My bash file is made executable by chmod +x bashfile.sh
What I am trying to do is this:
Find pdfs or eps files and populate pdfs.file and eps.file with their file names.
Step through row by row and grab these file names and append to $pwd.
Then append $pwd$var to the include graphics command in latex.
I'm not sure what you're doing wrong, but this works fine for me:
for i in {1..2}; do
echo $PWD
echo $PWD > /tmp/testfile
done
echo "File contents: $(cat /tmp/testfile)"
This successfully returns the following:
/tmp
/tmp
File contents: /tmp
Did you write the bash file using a Windows editor? Maybe you have a problem with line terminators. Try dos2unix bashfile.sh.

Refer to the current directory in a shell script

How do I refer to the current directory in a shell script?
So I have this script which calls another script in the same directory:
#! /bin/sh
#Call the other script
./foo.sh
# do something ...
For this I got ./foo.sh: No such file or directory
So I changed it to:
#! /bin/sh
#Call the other script
foo.sh
# do something ...
But this would call the foo script which is, by default, in the PATH. This is not what I want.
So the question is, what's the syntax to refer ./ in a shell script?
If both the scripts are in the same directory and you got the ./foo.sh: No such file or directory error then the most likely cause is that you ran the first script from a different directory than the one where they are located in. Put the following in your first script so that the call to foo.sh works irrespective of where you call the first script from:
my_dir=`dirname $0`
#Call the other script
$my_dir/foo.sh
The following code works well with spaces and doesn't require bash to work:
#!/bin/sh
SCRIPTDIR="$(dirname "$0")"
#Call the other script
"$SCRIPTDIR/foo.sh"
Also if you want to use the absolute path, you could do this:
SCRIPTDIR=`cd "$(dirname "$0")" && pwd`
This might help you:
Unix shell script find out which directory the script file resides?
But as sarnold stated, "./" is for the current working directory.
In order to make it POSIX:
a="/$0"; a=${a%/*}; a=${a:-.}; a=${a#/}/; BASEDIR=$(cd $a; pwd)
Tested on many Bourne-compatible shells including the BSD ones.
As far as I know I am the author and I put it into public domain. For more info see:
https://blog.jasan.tk/posix/2017/05/11/posix_shell_dirname_replacement
script_dir="${BASH_SOURCE%/*}" # rm the last / and the file name from BASH_SOURCE
$script_dir/foo.sh
Reference: Alex Che's comment above.
The accepted solution does not work if you have a space in the path to the directory containing the scripts.
If you can use bash, this worked for me:
#!/bin/bash
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
"${SCRIPTDIR}/foo.sh"

Resources