linux releative path to fullpath file name - linux

I need a way of getting the fullpath name of a file on a linux shell script.
The full path may already be supplied or a relative file may be supplied.
afile.txt
/home/me/bfile.txt
to
/home/me/afile.txt
/home/me/bfile.txt
any ideas?

Use readlink(1).
readlink -f afile

Quick hack:
get_fn()
{
echo $(cd $(dirname $1); pwd)/$(basename $1)
}
But it can be costly.

If the directory will be the same, you can list the files in that directory in this way:
DIRECTORY=/some/directory
FILE_NAME="my-file-list"
for i in `ls -1 $DIRECTORY`
do
echo $i >> $FILE_NAME
done
Otherwise, you would use the FIND command in the How can I list files with their absolute path in linux?

Related

How to extract the directory from full file path

I have the following script which prints various file stats, which was kindly supplied by another user (choroba) (link).
Is there a way that this can be amended to report just the directory name of each file and not the full file path with the file name? I have tried changing filepath with dirname and I get a series of errors saying No such file or directory. Thanks for any advice.
#!/bin/bash
set -eu
filepath=$1
qfilepath=${filepath//\\/\\\\} # Quote backslashes.
qfilepath=${qfilepath//\"/\\\"} # Quote doublequotes.
file=${qfilepath##*/} # Remove the path.
stats=($(stat -c "%s %W %Y" "$filepath"))
size=${stats[0]}
ctime=$(date --date #"${stats[1]}" +'%d/%m/%Y %H:%M:%S')
mtime=$(date --date #"${stats[2]}" +'%d/%m/%Y %H:%M:%S')
md5=$(md5sum < "$filepath")
md5=${md5%% *} # Remove the dash.
printf '"%s","%s",%s,%s,%s,%s\n' \
"$file" "$qfilepath" "$size" "$ctime" "$mtime" $md5
You can use a combination of dirname and basename, where:
dirname will strip the last component from the full path;
basename will get the last component from the path.
So to summarize: $(basename $(dirname $qfilepath)) will give you the name of the last directory in the path.
Or, for the full path without the file name - just $(dirname $qfilepath).
Although I do not see anything in the script snippet which would produce a recursive list, you can get the directory name output with adding dir=$(dirname $filepath) and modifying your printf output to use $dir instead of $file.

Get current directory (not full path) with filename only when sub folder is present in Linux bash

I have prepared a bash script to get only the directory (not full path) with file name where file is present. It has to be done only when file is located in sub directory.
For example:
if input is src/email/${sub_dir}/Bank_Casefeed.email, output should be ${sub_dir}/Bank_Casefeed.email.
If input is src/layouts/Bank_Casefeed.layout, output should be Bank_Casefeed.layout. I can easily get this using basename command.
src/basefolder is always constant. In some cases (after src/email(basefolder) directory), sub_directories will be there.
This script will work. I can use this script (only if module is email) to get output. but script should work even if sub directory is present in other modules. Maybe should I count the directories? if there are more than two directories (src/basefolder), script should get sub directories. Is there any better way to handle both scenarios?
#!/bin/bash
filename=`basename src/email/${sub_dir}/Bank_Casefeed.email`
echo "filename is $filename"
fulldir=`dirname src/email/${sub_dir}/Bank_Casefeed.email`
dir=`basename $fulldir`
echo "subdirectory name: $dir"
echo "concatenate $filename $dir"
Entity=$dir/$filename
echo $Entity
Using shell parameter expansion:
sub_dir='test'
files=( "src/email/${sub_dir}/Bank_Casefeed.email" "src/email/Bank_Casefeed.email" )
for f in "${files[#]}"; do
if [[ $f == *"/$sub_dir/"* ]]; then
echo "${f/*\/$sub_dir\//$sub_dir\/}"
else
basename "$f"
fi
done
test/Bank_Casefeed.email
Bank_Casefeed.email
I know there might be an easier way to do this. But I believe you can just manipulate the input string. For example:
#!/bin/bash
sub_dir='test'
DIRNAME1="src/email/${sub_dir}/Bank_Casefeed.email"
DIRNAME2="src/email/Bank_Casefeed.email"
echo $DIRNAME1 | cut -f3- -d'/'
echo $DIRNAME2 | cut -f3- -d'/'
This will remove the first two directories.

Move files and rename - one-liner

I'm encountering many files with the same content and the same name on some of my servers. I need to quarantine these files for analysis so I can't just remove the duplicates. The OS is Linux (centos and ubuntu).
I enumerate the file names and locations and put them into a text file.
Then I do a for statement to move the files to quarantine.
for file in $(cat bad-stuff.txt); do mv $file /quarantine ;done
The problem is that they have the same file name and I just need to add something unique to the filename to get it to save properly. I'm sure it's something simple but I'm not good with regex. Thanks for the help.
Since you're using Linux, you can take advantage of GNU mv's --backup.
while read -r file
do
mv --backup=numbered "$file" "/quarantine"
done < "bad-stuff.txt"
Here's an example that shows how it works:
$ cat bad-stuff.txt
./c/foo
./d/foo
./a/foo
./b/foo
$ while read -r file; do mv --backup=numbered "$file" "./quarantine"; done < "bad-stuff.txt"
$ ls quarantine/
foo foo.~1~ foo.~2~ foo.~3~
$
I'd use this
for file in $(cat bad-stuff.txt); do mv $file /quarantine/$file.`date -u +%s%N`; done
You'll get everyfile with a timestamp appended (in nanoseconds).
You can create a new file name composed by the directory and the filename. Thus you can add one more argument in your original code:
for ...; do mv $file /quarantine/$(echo $file | sed 's:/:_:g') ; done
Please note that you should replace the _ with a proper character which is special enough.

Removing part of a filename for multiple files on Linux

I want to remove test.extra from all of my file names in current directory
for filename in *.fasta;do
echo $filename | sed \e 's/test.extra//g'
done
but it complains about not founding file.echo is to be sure it list correctly.
First of all use 'sed -e' instead of '\e'
And I would suggest you do it this way in bash
for filename in *.fasta; do
[ -f "$filename" ] || continue
mv "$filename" "${filename//test.extra/}"
done
Try rename "extra.test" "" *
Or rename 's/extra.test//;' *
$ find
./extra.test-eggs.txt
./extra.testbar
./fooextra.test
./ham-extra.test-blah
$ rename "extra.test" "" *
$ find
./-eggs.txt
./bar
./foo
./ham--blah
I know this thread is old, but the following oneliner, inspired from the validated answer, helped me a lot ;)
for filename in ./*; do mv "./$filename" "./$(echo "$filename" | sed -e 's/test.extra//g')"; done
Try the rename command:
rename 's/test.extra//g' *.fasta
$ mmv '*test.extra*.fasta' '#1#2.fasta'
This is safe in the sense that mmv will not do anything at all if it would otherwise overwrite existing files (there are command-line options to turn this off).
// EXTENSION - File extension of files
// STRING - String to be Replace
for filename in *.EXTENSION;
do [ -f "$filename" ] || continue;
mv "$filename" "${filename//STRING/}";
done
In Kali linux rename command is rename.ul
rename.ul 'string-to-remove' 'string-to-replace-with' *.jpg
example: rename.ul 'useless-string' '' *.jpg
This will delete useless-string from all the jpg image's filname.

Take the last part of the folder path in shell

If you type pwd you get something like:
/home/username/Desctop/myfolder/
How to take the last part? The myfolder path.
This must be simple but I couldn't find easy solution in shell. I know how to take care of this in java but not in shell.
thanks
You're right--it's a quick command:
basename "$PWD"
Using basename $(pwd) are two useless and expensive forks.
echo "${PWD##*/}"
should do the trick completely in the shell without expensive forks (snag: for the root directory this is the empty string).
In Linux, there are a pair of commands, dirname and basename. dirname extracts all but the last part of a path, and basename extracts just the last part of a path.
In this case, using basename will do what you want:
basename $(pwd)
You can use basename for that, provided the last part is indeed a directory component (not a file):
$ basename /home/username/Desctop/myfolder/
myfolder
To extract the last part of a path, try using basename...
basename $(pwd);
function basename {
shopt -s extglob
__=${1%%+(/)}
[[ -z $__ ]] && __=/ || __=${__##*/}
}
basename "$PWD"
echo "$__"

Resources