Is there any way/alternative to readlink -f in Linux to handle spaces present in the folder name? [duplicate] - linux

This question already has answers here:
I just assigned a variable, but echo $variable shows something else
(7 answers)
Closed 4 years ago.
My directory structure is /local/mnt/abcd/sub 1
So inside the 'sub 1' folder, I am trying to execute the following script
SOURCEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
readlink -f $SOURCEDIR/..
it gives output as : /local/mnt/abcd/sub not /local/mnt/abcd/sub\ 1
Basically, it is not able to handle if there is a space present in the folder name. So I want to know is there any alternative to readlink or any other way we can get the absolute path

You need to quote the parameter expansion so that readlink gets the path as a single argument.
readlink -f "$SOURCEDIR/.."
Without the quotes, it's equivalent to
readlink -f /local/mnt/abcd/sub 1/..

Put double-quotes round the argument to keep it as a single argument:
readlink -f "$SOURCEDIR/.."

Related

BASH "for ... in ..." don't work with variables [duplicate]

This question already has an answer here:
In bash, how do I expand a wildcard while it's inside double quotes?
(1 answer)
Closed 2 years ago.
I want to write a simple script that does something for every file in user-defined directory. Here's a script that works for predefined directory:
for file in mydir/*; do
printf "$file"
done
Here's similar script that prints name of each file in the directory defined by variable:
for file in "$nicedir*"; do
printf "$file"
done
This second script don't work. Of course, I remembered about slash at the end of the path. (I passed ./ as the argument instead of just .)
Pathname expansion doesn't happen in quoted strings. Keep the wildcard outside of the quotes:
for file in "$nicedir"* ; do
printf '%s\n' "$file"
done
The final slash is usually not required in paths, so you'll more often see
for file in "$nicedir/"*
# or equivalent
for file in "$nicedir"/*

How to check if the folders are the same using variables in Bash? [duplicate]

This question already has answers here:
How to check if two paths are equal in Bash?
(5 answers)
Closed 4 years ago.
given the bash code below, i am defining a variable to represent a folder and i am checking if it is a folder. I can even browse into it using the variable name.
There is a small catch here, i defined the folder's name with '/' as the last character, because the tab completion completes the string this way.
#! /bin/bash
VAR_LOG='/var/log/'
echo $VAR_LOG
echo $PWD
echo "browsing to log directory"
cd $VAR_LOG
echo $PWD
if [ -d $VAR_LOG ]; then
echo "$VAR_LOG is a directory"
fi
if [ ${VAR_LOG} != ${PWD} ]
then echo not same
else
echo same
fi
But as you can see, $PWD defines the same path/folder without '/' as the last character and the string comparison will result as false. Even though i am in the same folder and the cd $LOG_DIR will take me to the same folder.
User1-MBP:log User1$ $HOME/tmp.sh
/var/log/
/Users/User1
browsing to log directory
/var/log
/var/log/ is a directory
not same
So, what is the best way to work with directories in bash? Keeping them as strings is somewhat error-prone.
(NOTE: this is a MacOS system - i am not sure if it should make any difference)
Thanks a lot..
If you only care about string equality, you can strip the trailing \ from VAR_LOG by using ${VAR_LOG%/} expansion (Remove matching suffix pattern). This will strip one (last / from VAR_LOG if present and leave it unchanged when not:
if [ "${VAR_LOG%/}" != "${PWD}" ]; ...
However, you can also (and probably should) use -ef test:
FILE1 -ef FILE2
FILE1 and FILE2 have the same device and inode numbers
I.e.:
if [ ! "${VAR_LOG}" -ef "${PWD}" ]; ...
Ensure both file/directory names refer to the same file.
This is not relevant for directories, but different filenames referring to the same inode (hardlinks) would evaluate to 0 on -ef test.

shell script to list file names alone in a directory & rename it [duplicate]

This question already has answers here:
How can I remove the extension of a filename in a shell script?
(15 answers)
Closed 6 years ago.
I'm new to scripting concept.. I have a requirement to rename multiple files in a directory like filename.sh.x into filename.sh
First I tried to get the file names in a particular directory.. so i followed the below scripting code
for entry in PathToThedirectory/*sh.x
do
echo $entry
done
& the above code listed down all the file names with full path..
But my expected o/p is : to get file names alone like abc.sh.x,
so that I can proceed with the split string mechanism to perform rename
operation easily...
help me to solve this ... Thanks in advance
First approach trying to follow OP suggestions:
for i in my/path/*.py.x
do
basename=$(basename "$i")
mv my/path/"$basename" my/path/"${basename%.*}"
done
And maybe, you can simplify it:
for i in my/path/*.py.x
do
mv "$i" "${i%.*}";
done
Documentation regarding this kind of operation (parameter expansion): https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
In particular:
${parameter%word} : The word is expanded to produce a pattern just as in filename expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the ‘%’ case) or the longest matching pattern (the ‘%%’ case) deleted
So, ${i%.*} means:
Take $i
Match .* at the end of its value (. being a literal character)
Remove the shortest matching pattern
Look into prename (installed together with the perl package on ubuntu).
Then you can just do something like:
prename 's/\.x$//' *.sh.x
In ksh you can do this:
for $file in $(ls $path)
do
new_file=$(basename $path/$file .x)
mv ${path}/${file} ${path}/${new_file}
done
This should do the trick:
for file in *.sh.x;
do
mv "$file " "${file /.sh.x}";
done
Running this rename command from the root directory should work:
rename 's/\.sh\.x$/.sh/' *.sh.x
for i in ls -la /path|grep -v ^d|awk '{print $NF}'
do
echo "basename $i"
done
it will give u the base name of all files or you can try below
find /path -type f -exec basename {} \;

Bash script can't find file in relative path directory [duplicate]

This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Closed 1 year ago.
I'm new to bash and I am trying to create a script that should find an archive in a given directory. $1 is the name of archive.
When the given path is ./1/ar.tgz the script works. But when path is ../data 1/01_text.tgz I have the following problem:
dirname: extra operand "1/01_text.tgz"
and then No such file or directory.
Here is my code fragment:
VAR=$1
DIR=$(dirname ${VAR})
cd $DIR
What am I doing wrong?
Ahmed's answer is right, but you also need to enclose VAR in double quotes. The correct code fragment is:
VAR=$1
DIR=$(dirname "$VAR")
cd "$DIR"
The space is causing the problem: cd $DIR gets expanded to cd ../data 1/01_text.tgz and cd doesn't know what to make of the third "argument". Add quotes around the directory: cd "$DIR".

List paths with find when the filename contains spaces [duplicate]

This question already has answers here:
Iterate over a list of files with spaces
(12 answers)
Closed 9 years ago.
I have this code
for i in $(find pwd)
do
echo $i
done
the problem is if the file name contains spaces, it prints on a separate line
how can I list all of the files in some directory including files that contains spaces
This would have the intended effect of your example:
find /path/to/somewhere
That is, no need to wrap a for loop around it.
But I'm guessing you want something more than just echoing. Perhaps call a script for each file? You can do that with:
find /path/to/somewhere -exec path/to/script.sh {} \;
where {} will be replaced for each filename found.
I would use while read for this.
find . | while read i; do echo $i; done;
Edit:
Alternatively, you could just do ls -a1
here is the solution
IFS=$'\n'
for i in $(pwd)
do
echo $i
done

Resources