List absolute path for folder in Linux and Perl - linux

I have a folder where inside that contains two folder such as below:
/vobs/code
/vobs/code/item
/vobs/code/image
I would like to obtain its absolute path of the two folder.In my perl script my code looks like this .
#folder = `cd /vobs/code/item;ls -d $PWD/**`; or
#folder = `cd /vobs/code/item;ls -d $PWD/*`;
From online it says that with the two wild card it will display files and directories while one wild card display folder but I tried in the console it gives files and folder also with or extra one wild card.
The result that I get after executing the perl script it does not give the folder path inside /vobs/code.Instead it display the root folder path.I put a pwd in between the cd and ls the pwd shows that it actually cd to the directory and perform the next command.
#folder = `cd /vobs/code/item;ls -d $pwd/*`
The command above produce the same output as the first and 2nd command as the pwd is lower case and it display root folder path.
I tried readlink -f but it requires the folder name else it will prompt error.I can try to get the file name and pwd the path and join it to become a variable but it is kind of hassle and I would take it as final resort if I could not find any solutions.Please help Thanks

You can use glob to expand a wildcard. Use grep to filter a list, -f and -d (see -x) check for files and directories, respectivelly.
my #files_and_directories = glob '/vobs/code/*';
my #files = grep -f, #files_and_directories;
my #directories = grep -d, #files_and_directories;

Have you considered abs_path?
use Cwd 'abs_path';
my $base_path = abs_path('vobs/code');
for my $dir ( qw/item image/ ){
my $path = abs_path(join("/",$base_path,$dir));
# Ofc, this will only work if vobs/code is in working directory.
my #files_in_dir = grep{ -f $_ }<$path/*>; # these will be absolute
}

Related

List all folder and subfolder inside it where folder names start with a* or b* or c* with path

I need a folder and subfolder inside it to be displayed where names that start with A* or B* or C* and display along with path
Below Command Does not Display as expected
$ ls -l | egrep d
You can display the current directory by using the system environment variable PWD. You can combine the PWD with your ls command
using ls -ld
ls -ld $PWD/A* $PWD/B* $PWD/C*
EDIT
If you want a list of all the directories and sub directories you can use the find command.
find . > subfolders.txt && cat subfolders.txt | egrep -i "^./E|^./g"
This command will recursively list all contents on your current working directory and send the output to a txt file named subfolders.txt. Then it will read the contents of subfolders.txt and using egrep, you can filter out anything that starts with "./E" or "./g". the -i option means it is case insensitive.
NOTE: This will also display the files contained in those subfolders.
find . | grep -E '/A|/B|/C'
find is better than ls for your requirements.

How to get a folder name in linux bash from a directory

There will be directory which will have any number folder and may be files, I just need pick one random folder and need to process it ( move the folders , etc ..) I need process folder one by one. Need to ignore if there is any files.
I am tiring with below code able to get folder name but , seems there some hidden character or some thing which not giving proper output.
PROCESSING_FOLDER_NAME= ls -l /ecom/bin/catalogUpload/input/TNF-EU/ | grep '^d' | cut -d ' ' -f23 | head -1
#PROCESSING_FOLDER_NAME= echo $PROCESSING_FOLDER_NAME | tr -d '\n\r'
#PROCESSING_FOLDER_NAME=${PROCESSING_FOLDER_NAME%$'\n'}
#echo "PROCESSING_FOLDER_NAME is/$PROCESSING_FOLDER_NAME "
echo "/ecom/bin/catalogUpload/input/TNF-EU/$PROCESSING_FOLDER_NAME/"
output
Thanks_giving_Dec_08
/ecom/bin/catalogUpload/input/TNF-EU//
I am expecting the output should be /ecom/bin/catalogUpload/input/TNF-EU/Thanks_giving_Dec_08/
Here is my bash version.
GNU bash, version 4.2.50(1)-release (powerpc-ibm-aix6.1.2.0)
I mainly need the folder name (not full path) in variable, As the folder name which is processing need be use for emails to notify other, etc.
To get a random folder from a list of folders,
first put the list of folders in an array:
list=(/ecom/bin/catalogUpload/input/TNF-EU/*/)
Next, get a random index using the $RANDOM variable of the shell,
modulo the size of the list:
((index = RANDOM % ${#list[#]}))
Print the value at the selected index:
echo "${list[index]}"
To get just the name of the directory without the full path, you can use the basename command:
basename "${list[index]}"
As for what's wrong with the original script:
To store the result of a command in a variable, the syntax is name=$(cmd) instead of name= cmd
Do not parse the output of ls, it's not reliable
To get directories in a directory, you can use glob patterns like * ending with /, as in the above example */.

output to a file in script directory

This probably quite basic but I have spent whole day finding an answer without much success.
I have an executable script that resides in ~/Desktop/shell/myScript.sh
I want a single line command to run this script from my terminal that outputs to a new directory in same directory where the script is located no matter what my present working directory is.
I was using:
mkdir -p tmp &&
./Desktop/shell/myScript.sh|grep '18x18'|cut -d":" -f1 > tmp/myList.txt
But it creates new directory in present working directory and not on the target location.
Any help would be appreciated.
Thanks!
You could solve it in one line if you pre-define a variable:
export LOC=$HOME/Desktop/shell
Then you can say
mkdir -p $LOC/tmp && $LOC/myScript.sh | grep '18x18' | cut -d":" -f1 > $LOC/tmp/myList.txt
But if you're doing this repeatedly it might be better long-term to wrap myScript.sh so that it creates the directory, and redirects the output, for you. The grep and cut parameters, as well as the output file name, would be passed as command-line arguments and options to the wrapper.
How about this:
SCRIPTDIR="./Desktop/shell/" ; mkdir "$SCRIPTDIR/tmp" ; "$SCRIPTDIR/myScript.sh" | grep '18x18' | cut -d ":" -f 1 > "$SCRIPTDIR/tmp/myList.txt"
In your case you have to give the path to the script anyway. If you put the script in the path where it is automatically searched, e.g. $HOME/bin, and you can just type myScript.sh without the directory prefix, you can use SCRIPTDIR=$( dirname $( which myScript.sh ) ).
Mixing directories with binaries and data files is usually a bad idea. For temporary files /tmp is the place to go. Consider that your script might become famous and get installed by the administrator in /usr/bin and run by several people at the same time. For this reason, try to think mktemp.
YOUR SCRIPT CAN DO THIS FOR YOU WITH SOME CODES
Instead of doing this manually from the command line and who knows where you will move your script and put it. add the following codes
[1] Find your script directory location using dirname
script_directory=`dirname $0`
The above code will find your script directory and save it in a variable.
[2] Create your "tmp" folder in your script directory
mkdir "$script_directory/tmp 2> /dev/null"
The above code will make a directory called "tmp" in your script directory. If the directory exist, mkdir will not overwrite any existing directory using this command line and gave an error. I hide all errors by "2> /dev/null"
[3] Open your script and modify it using "cut" and then redirect the output to a new file
cat "$0"|grep '18x18'|cut -d":" -f1 > "$script_directory"/tmp/myList.txt

Linux Shell script what dirname and ? means?

Can any body tell me what this command means?
selfDir=$(cd "$(dirname "$0")"; pwd) ?
I know
$0 = running script name
pwd = current working dir
cd = to change dir
What I need is what is dirname? and what ? means at end to make this line completely understandable.
The dirname command removes the trailing / component from the NAME and prints the remaining portion. If the NAME does not contain / component then it prints '.' (means current directory)
Dirname Command Example:
Remove the file name from absolute path.
Let say my directory path is /usr/local/bin/add.sh. Now i want to remove /add.sh and display only /usr/local/bin, then we can use the dirname command.
dirname /usr/local/bin/add.sh
/usr/local/bin
NAME
dirname - strip non-directory suffix from file name
SYNOPSIS
dirname NAME
dirname OPTION
DESCRIPTION
Print NAME with its trailing /component removed; if NAME contains no /’s, output ‘.’ (meaning the current directory).
Edit:
Also, Some characters have special functions in linux commands ? <-- Matches one character
Source

copy files along with their (last) folders

I can find and copy all the files to a given folder using find -exec command.
But what I need to do is to find and copy all the files within a given path along with its folder in which it has been saved. So ....
/path/to/file/is/abc.txt
/another/file/is/here/xyz.txt
I need to copy these 2 files along with their path to the following folder:
/mysql/data/
The new file structure will look like this...
/mysql/data/is/abc.txt
/mysql/data/here/xyz.txt
This is done in order to avoid possible overwrite of duplicate file names. The last folder names will be unique but file names may be the same.
What is the best way to do this?
Here's a concise script with a rather long explanation* to accompany it.
for oldpath in $your_file_list; do
mv ${oldpath} /mysql/data${oldpath##$(dirname $(dirname $oldpath))}
done
How it works
The dirname utility removes everything up to and including the last forward slash (/) from a path. Invoking it twice will remove everything up to and including the second-to-last slash.
The idiom $(command with params) executes command with the parameters with params and returns the output.
The idiom ${var##prefix} returns the contents of the variable var with prefix removed.
Step-by-step Analysis
If oldpath is /path/to/file/is/abc.txt, then:
dirname $oldpath is /path/to/file/is
dirname $(dirname $oldpath) is /path/to/file
${oldpath##$(dirname $(dirname $oldpath))} is /is/abc.txt
which is the portion of the original path that will be appended to the new path.
* Elegant (adj.) software: any software that implements an algorithm, whose explanation is longer than the implementation itself.
You're going to have to script/program this solution.
Quick python example follows:
import os
import shutils
src_root = '/path/to/walk/'
dst_root = '/mysql/data/'
for root,dirs,files in os.walk(src_root):
for file in files:
dst_path = os.path.split(root)[1]
dst_path = os.path.join(dst_root, dst_path)
os.makedirs(dst_path)
src = os.path.join(root,i file)
dst = os.path.join(dst_path, file)
shutils.copyfile(srd, dst)
This might work for you:
a=/mysql/data
sed 's|.*\(/[^/]*/[^/]*\)|mv -v & '"$a"'\1|' file
mv -v /path/to/file/is/abc.txt /mysql/data/is/abc.txt
mv -v /another/file/is/here/xyz.txt /mysql/data/here/xyz.txt
Study the output and if all OK, then run:
sed 's|.*\(/[^/]*/[^/]*\)|mv -v & '"$a"'\1|' file | bash
If you want to copy a file first you need to create a directory for it. You can do that using single find command, but I'm not sure about efficiency of this solution?
#!/bin/bash
# $1 - destination
find $1 -type f -exec bash -c '
dest="$2"; # $2 is second argument passed to the script
dir=$(basename $(dirname $1));
mkdir $dest/$dir 2>/dev/null;
cp $1 "$dest/$dir/";
' -- {} $2 \; # {} = $1 in bash '..' and $2=$2
usage: ./copy copy_from copy_to
edit:
that looks better:
#!/bin/bash
dest=$2
from=$1
# copy_file from dest
copy_file() {
dir=$(basename $(dirname $from))
mkdir $dest/$dir
cp $from $dest/$dir
}
find $from -type f | while read file; do copy_file $file $dest; done

Resources