Need help to move files from one directory to another with shell script - sh

There will be a directory, which will contain various file types(xlsx, gpg, txt).
If .gpg then only invoke the decrypt.sh or else move the file to output folder.
Anyone who could help me the same?

Assuming bash (likely), you can iterate over the files in a directory with the for command, such as in the following transcript:
pax> ls -al
total 4
drwxr-xr-x 5 pax ubergeeks 0 Jun 7 16:01 .
drwxr-xr-x 1 pax ubergeeks 8192 Jun 7 16:01 ..
-rw-r--r-- 1 pax ubergeeks 0 Jun 7 16:01 file 1.txt
-rw-r--r-- 1 pax ubergeeks 0 Jun 7 16:01 file 2.gpg
-rw-r--r-- 1 pax ubergeeks 0 Jun 7 16:01 file 3.xlsx
pax> for fspec in *.txt *.gpg *.xlsx ; do
...> echo "==> '$fspec'"
...> done
==> 'file 1.txt'
==> 'file 2.gpg'
==> 'file 3.xlsx'
You can test if a string variable ends in a specific string by using the regular expression operator:
if [[ "${fspec}" =~ \.gpg$ ]] ; then
echo it ends with .gpg
fi
And, of course, you can run a script or move a file with commands like:
/path/to/decrypt.sh "${fspec}
mv "${fspec}" /path/to/output
So, combining all that, a good starting point would be (making sure you specify real paths rather than my /path/to/ placeholders):
#!/usr/bin/env bash
cd /path/to/files
for fspec in *.txt *.gpg *.xlsx ; do
if [[ "${fspec}" =~ \.gpg$ ]] ; then
echo "Decrypting '${fspec}'"
/path/to/decrypt.sh "${fspec}"
else
echo "Moving '${fspec}'"
mv "${fspec}" /path/to/output
fi
done

Related

How do I create multiple directories within a directory that's in a directory with a single line command

so my path is from the desktop and I tried: mkdir OS\LAB1\Finance,Public,Archive,Customer
The command makes the first 3 directories but the last three get made on my desktop and not within LAB1,how do I do it with one command line?
Thank you
not a one liner, but this does the trick
$folders = #(,'Public','Archive','Customer')
New-Item -ItemType Directory C:\OS\LAB1\Finance\ -Force
foreach($folder in $folders){
New-Item -ItemType Directory C:\OS\LAB1\Finance\$folder -Force
}
The force parameter creates all the directories in one go.
I think that you want to create 4 directories under LAB1 not a single directory four deep. in Bash you can do this.
for i in $(tr ',' '\n' <<< "Finance,Public,Archive,Customer"); do mkdir "$i"; done
Result looks like this
0 drwxr-xr-x# 7 camerontownshend staff 224 16 Mar 12:28 .
0 drwxr-xr-x# 147 camerontownshend staff 4704 16 Mar 11:13 ..
0 drwxr-xr-x# 2 camerontownshend staff 64 16 Mar 12:28 Archive
0 drwxr-xr-x# 2 camerontownshend staff 64 16 Mar 12:28 Customer
0 drwxr-xr-x 2 camerontownshend staff 64 16 Mar 12:28 Finance
0 drwxr-xr-x# 2 camerontownshend staff 64 16 Mar 12:28 Public
Explanation
for i in ... -> for loop
tr ',' '\n' -> replaces commas with new lines
do mkdir "$i" done -> run whatever is inside the do/done pair. The mkdir "$i" - substitutes the iterator from the loop as a variable into the mkdir command
To create multiple folders (full paths) in one line using a list (caution: no spaces after commas):
$ mkdir -p /tmp/{test1,test2}
To verify:
$ ls /tmp/test*
/tmp/test1:
/tmp/test2:

Alias directory minus one file

I'd like to make an alias for a directory that contains many files. If I open the aliased directory, I want to view all files except for one. New files will be added to the directory over time, and I want everything to be aliased except for the one file permanently not-aliased.
Is it possible to set this up without needing to run a script every time a file in the directory changes?
E.g.: myDir contains fileA, fileB, and fileC.
I want myAliasedDir to contain fileA and fileB, but not fileC.
Can you get away with symbolic links?
Assuming your shell is bash:
$ shopt -s extglob
$ mkdir dir1 dir2
$ cd dir1
$ touch file{1..3}
$ ls -l
total 0
-rw-r--r-- 1 jackman jackman 0 Apr 1 12:40 file1
-rw-r--r-- 1 jackman jackman 0 Apr 1 12:40 file2
-rw-r--r-- 1 jackman jackman 0 Apr 1 12:40 file3
$ cd ../dir2
$ for f in ../dir1/!(file2); do ln -s "$f"; done
$ ls -l
total 8
lrwxrwxrwx 1 jackman jackman 13 Apr 1 12:41 file1 -> ../dir1/file1
lrwxrwxrwx 1 jackman jackman 13 Apr 1 12:41 file3 -> ../dir1/file3

Need to remove files with spaces in Debian

I need to find and remove files with spaces in them in a certain folder.
$ ls -l
total 16
-rw-r--r-- 1 smw staff 10 Feb 6 16:10 Foo Bar
-rw-r--r-- 1 smw staff 11 Feb 6 16:10 foobar
$ ls -l *\ *
-rw-r--r-- 1 smw staff 10 Feb 6 16:10 Foo Bar
$ rm -i *\ *
remove Foo Bar? y
$ ls -l
total 16
-rw-r--r-- 1 smw staff 11 Feb 6 16:10 foobar
You'll have to deal with bash's niceties when dealing with spaces...
First, you need to iterate over the files, in a way that gives you the files properly regardless of spaces. Check out this question. I'd favor this:
find ... | while read line ; do command "$line" ; done
And then it's a matter of using something like sed to change $line into whatever you need (such as the same thing without spaces) right where command "$line" is.
This is how I removed a file with a space
pi#raspberrypi ~/Music $ ls -l
-rw-r--r-- 1 pi pi 0 Feb 25 16:05 Sleep Away.mp3
pi#raspberrypi ~/Music $ rm Sleep\ Away.mp3
use the "\" forward slash to escape any spaces

How to delete a NULL file from Solaris Unix?

I have a NULL file in a directory:
-rw-r--r-- 1 blah1 blah2 83532 Nov 5 09:34 <can't see, but null here>
How do I remove this? This is very annoying as it interferes with svn status.
Thanks for any help.
Delete interactively, saying no to all of the non-null files.
/bin/rm -i *
You can remove using the iNode value (using the -i option on ls command)
# ls -li
total 16
30475938 -rw-r--r-- 1 root root 7 mar 19 10:29 -h
# find . -inum 30475938 -print
./-h
# find . -inum 30475938 -exec rm {} \;
# ls -li
total 0
In my blog, you have some examples -in Spanish- how to remove files with reserved characters.
http://sparcki.blogspot.com.es/2010/03/como-eliminar-archivos-utilizando-su.html
Urko,

What is the best way to extract a version string from a file?

I want to use a file to store the current version number for a piece of customer software which can be used by a start-up script to run the binary in the correct directory.
For Example, if the run directory looks like this:
.
..
1.2.1
1.2.2
1.3.0
run.sh
current_version
And current_version contains:
1.2.2
I want run.sh to descend into 1.2.2 and run the program foo.
The current solution is this:
#!/bin/sh
version = `cat current_version`
cd $version
./foo
It works but is not very robust. It does not check for file existence, cannot cope with multiple lines, leading spaces, commented lines, blank files, etc.
What is the most survivable way to do this with either a shell or perl script?
That's a common approach. You can check for dir/file existence using test operators such as "if [ -d "somedirectory" ]; then" or [ -t "somefile" ]
I use symbolic links more often, though. Then, you can just change your symbolic link to use the version you want.
For example,
$ ln -s 1.2.2 current_version
$ ls -al
total 20
drwxr-xr-x 5 dbreese dbreese 4096 2008-09-15 13:34 .
drwxr-xr-x 3 dbreese dbreese 4096 2008-09-15 13:34 ..
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.2.1
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.2.2
drwxr-xr-x 2 dbreese dbreese 4096 2008-09-15 13:34 1.3.0
lrwxrwxrwx 1 dbreese dbreese 6 2008-09-15 13:34 current_version -> 1.2.2/
Then your script can just use "cd current_version".
I would change the script to accept an argument. The argument should be a filename. Open the file using whatever scripting language you prefer [perl, python] and traverse the file until you find a match for your version.
I would use a regex... something along the lines of /\d\.\d\.\d/ . then have it execute the application through your script.
You can check for existence using the && and || operators:
!$/bin/sh
version = `cat current_version`
cd $version && ./foo || echo "Bad version"
The && operator causes the second statement to only execute if the first one succeeds (exit status 0), and the || operator causes the second statement to execute only if the first one fails (exit status non-zero).
I'm not sure what you mean by coping with multiple lines, leading spaces, or commented lines.
If the versioning will always be in #.#.# format, you could do this:
ls | grep ^[0-9]\.[0-9]\.[0-9]$ | sort -nr | head -n 1
That will list the versions in descending numerical order, then selects the first of those
What about:
#!/usr/bin/perl -w
use strict;
use warnings;
my $version_file = 'current_version';
open my $fh, '<', $version_file or die "Can't open $version_file: $!";
# Read version from file
my $version = <$fh>;
chomp $version;
# Remove whitespace (and match version)
die "Version format not recognized" if $version !~ m/(\d+\.\d+\.\d+)/;
my $dir = $1;
die "Directory not found: $dir" unless -d $dir;
# Execute program in versioned directory.
chdir $dir;
system("./foo");
!#/bin/sh
if [ -e 'current_version' ]; then
version=`cat current_version`;
version=`echo $version | tr -ds [[:blank:]]`
if [ -n "$version" ]; then
if [ -d "$version" ]; then
cd "$version"
else
echo $version is not a directory
fi
else
echo version_file contained only blanks
fi
else
No file named current_version exists
fi