How to overwrite the empty files in a directory? - shell

I am new to shell scripting.How to overwrite the empty files in a directory using shell scripting?
Can anyone help me above question...

Your question is pretty unspecific, please add tags and explain what scripting language you mean (eventually tell the OS you're using it).
With bash, you can overwrite files like this:
With mv: mv -f sourcefile /path/to/existing/destfile
With cp: cp overwrites files per default. To disable that behaviour, use the -n option

If the files are really empty, I guess you overwrite them not for resetting the content, but change the times (atime, mtime ...)
If it is true, touch is the tool to use. man touch to learn the usage.
If you have a source file, you can just cp or mv as #weeheavy suggested.

Related

Using functions as an argument in Bash

I want to move a couple of files from point a to point b
but I have to manually specify
mv /full/path/from/a /full/path/to/b
but some times there are 20 files which I have to move manually. Instead of /full/path/form/a, can't I just enter the a function which returns all the files which I want to move in my case;
/full/path/to/b is a directory, it's the target directory which all the files with extenstions mp3, exe and mp4 must go to:
mv ls *.{mp3,exe,mp4} /full/path/to/b
If I have to move a couple of files and I don't want to do it one by one, how can I optimize the problem?
The command mv ls *.{mp3,exe,mp4} /full/path/to/b in your question is not correct.
As pointed out in comments by #janos, the correct command is
mv *.{mp3,exe,mp4} /full/path/to/b
mv can complain about missing file if the file is really missing and/or the path is not accessible or is not valid.
As i can understand by your question description, if you go manually to the source path you can move the file to the desired directory.
Thus it seems that path is valid, and file exists.
In order mv to keeps complaining about *.mp3 not found (having a valid path and file) the only reason that pops up in my head is the Bash Pathname Expansion feature (enabled by default in my Debian).
Maybe for some reason this pathname expansion bash feature is disabled in your machine.
Try to enable this feature using command bellow and provide the correct command to mv and you should be fine.
$ set +f
PS: Check man bash about pathname expansion.

Is it safe to alias cp -R to cp?

When I copy something, I always forget the -R, then I have go all the way back to add it right after cp.
I want to add this to bash config files.
alias cp="cp -R"
I have not seen anything bad happen. Is it safe to do this?
The only thing I can think of that would cause unexpected behavior with the -R flag is that it doesn't work with wildcards.
What I mean is... for example you want to copy all mp3 Files in a directory and every subdirectory with: cp -R /path/*.mp3. Although -R is given it will not copy mp3s in the subdirectories of path - if there are any.
I wouldn't use aliases for changing the behaviour of normal commands. When you are in a different shell / another computer, the alias will be missing. When a friend wants to help you, he will not know what you did.
Once I had an alias rm="rm -i" and I performed rm *, while I just had changed shell with a su.
And sometimes you want to use cp without the -R option, will you remember to use /bin/cp in these cases (copy all files in the current dir to another location, but do not cp the subdirs)?

How to move files of "specific extension" ( from directories ) to a new location while maintaining full directory structure ?

I have following directory structure :
/home/dir1/abc.jpg
/home/dir1/abc.pdf
/home/dir1/dir2/abc.jpg
/home/dir1/dir2/abc1.jpg
/home/dir1/dir2/dir3/abc.jpg
and I want to copy jpg files from them to a new folder which will have same directory structure, for eg.:
/home/newdir1/abc.jpg
/home/newdir1/dir2/abc.jpg
/home/newdir1/dir2/abc1.jpg
/home/newdir1/dir2/dir3/abc.jpg
How to achieve it using rsync or any other software ?
Please help, Many Thanks !!
From the looks of what you've included in your question, there are a couple of things you might try.
You've specified that you want to "move" files. That means you either use the mv command, or use rsync's --remove-source-files option. For example:
mv /source1/* /source2/* /path/to/targetdir/
or
rsync -a /source1/ /source2/ /path/to/targetdir/
You've no doubt already read the part of rsync's man page that explains the difference between source dirs with and without their trailing slash. If not, read up, because it's important.
If your "thousands of source files [with] similar names" need to be matched from within your source directories, leaving some other files behind, you need to determine whether your "similar names" can be differentiated using pathname expansion or if you should use a regular expression. If the former, then adding the pathname expansion to your sources with either mv or rsync should be sufficient. If you need to use a regex, then find may be a better option:
find /source1/ /source2/ -regex ".*/file[A-F][0-9][0-9].txt" -exec mv "{}" /targetdir/ \;
If these don't solve the problem, then you'll need to supply more detail in your question.
I would try a little shell script like this:
#!/bin/sh
cd /home/dir1
JPEGS=`find . -name "*.jpg"`
tar cf - $JPEGS | (cd /home/newdir1 ; tar xf -)
This first gets the list of all your jpg files with their relative paths, then writes a tar file of them to a pipe into a subshell which changes to the new directory, and then extracts the tar from its stdin.

Mac terminal: Deleting files from a folder whose name is equal to files in another folder

The layout of the two directories in question is:
folder1
-file1
-file2
folder2
-file1
-file2
The files in the directories are named the same. I tried to use rm to programmatically remove files in folder 2:
for f in /Users/michelegiarratana/1/*; do rm /Users/michelegiarratana/2/$f
but this isn't working. Is $f the full path? How do I get the name?
Thanks
As savanto said in his comment -- yes, you are correct, $f here is the full file path. To fix this, you should use the basename builtin, which extracts just the file name. In your example:
for f in /Users/michelegiarratana/1/*; do rm /Users/michelegiarratana/2/$(basename $f); done
Additionally -- your question applies more broadly to bash shells than just the OS X terminal, in the future, you should try looking for answers in the bash tag, as many of them will be useful to you.

Bash script to archive files and then copy new ones

Need some help with this as my shell scripting skills are somewhat less than l337 :(
I need to gzip several files and then copy newer ones over the top from another location. I need to be able to call this script in the following manner from other scripts.
exec script.sh $oldfile $newfile
Can anyone point me in the right direction?
EDIT: To add more detail:
This script will be used for monthly updates of some documents uploaded to a folder, the old documents need to be archived into one compressed file and the new documents, which may have different names, copied over the top of the old. The script needs to be called on a document by document case from another script. The basic flow for this script should be -
The script file should create a new gzip
archive with a specified name (created from a prefix constant in the script and the current month and year e.g. prefix.september.2009.tar.gz) only if it
does not already exist, otherwise add to the existing one.
Copy the old file into the archive.
Replace the old file with the new one.
Thanks in advance,
Richard
EDIT: Added mode detail on the archive filename
Here's the modified script based on your clarifications. I've used tar archives, compressed with gzip, to store the multiple files in a single archive (you can't store multiple files using gzip alone). This code is only superficially tested - it probably has one or two bugs, and you should add further code to check for command success etc. if you're using it in anger. But it should get you most of the way there.
#!/bin/bash
oldfile=$1
newfile=$2
month=`date +%B`
year=`date +%Y`
prefix="frozenskys"
archivefile=$prefix.$month.$year.tar
# Check for existence of a compressed archive matching the naming convention
if [ -e $archivefile.gz ]
then
echo "Archive file $archivefile already exists..."
echo "Adding file '$oldfile' to existing tar archive..."
# Uncompress the archive, because you can't add a file to a
# compressed archive
gunzip $archivefile.gz
# Add the file to the archive
tar --append --file=$archivefile $oldfile
# Recompress the archive
gzip $archivefile
# No existing archive - create a new one and add the file
else
echo "Creating new archive file '$archivefile'..."
tar --create --file=$archivefile $oldfile
gzip $archivefile
fi
# Update the files outside the archive
mv $newfile $oldfile
Save it as script.sh, then make it executable:
chmod +x script.sh
Then run like so:
./script.sh oldfile newfile
something like frozenskys.September.2009.tar.gz, will be created, and newfile will replace oldfile. You can also call this script with exec from another script if you want. Just put this line in your second script:
exec ./script.sh $1 $2
A good refference for any bash scripting is Advanced Bash-Scripting Guide.
This guide explains every thing bash scripting.
The basic approach I would take is:
Move the files you want to zip to a directory your create.
(commands mv and mkdir)
zip the directory. (command gzip, I assume)
Copy the new files to the desired location (command cp)
In my experience bash scripting is mainly knowing how to use these command well and if you can run it on the command line you can run it in your script.
Another command that might be useful is
pwd - this returns the current directory
Why don't you use version control? It's much easier; just check out, and compress.
(apologize if it's not an option)

Resources