LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Adding additional commands to a bash shell script (https://www.linuxquestions.org/questions/linux-newbie-8/adding-additional-commands-to-a-bash-shell-script-907666/)

iwitham 10-11-2011 05:54 PM

Adding additional commands to a bash shell script
 
I have a simple script that removes old files from a directory:

#! /bin/bash
set -o errexit
set -o nounset

# Get a list of files that meet the critera for removal.


for file in `find <My_Directory> -type f -mtime +2`;
do rm -f $file;
done

However, I want to add the following to it:

for file in *;
do mv "$file" `echo $file | sed -e 's/ */_/g' -e 's/_-_/-/g'`;
done

Is it possible and if so how can I do it?

grail 10-11-2011 07:45 PM

I am not sure I see the issue here? I would guess that the files being removed are not the ones being renamed, so simply add the new code??

Ian John Locke II 10-11-2011 07:47 PM

If you do not want to remove the files you can do
Code:

#!/bin/bash

set -o errexit
set -o nounset

for file in *; do
  mv "$file" "$(echo $file | sed -e 's/ */_/g' -e 's/_-_/-/g')"
done

If you want to keep the removal of the files, I have no clue what you're asking.

iwitham 10-11-2011 08:40 PM

I have discovered that some of the files in the directory have spaces. They need to be deleted as well, but I cannot think of a way to do that straight up.

chrism01 10-11-2011 08:47 PM

find should return the entire fname, inc spaces. Put double quotes around it for the rm cmd
Code:

for file in `find <My_Directory> -type f -mtime +2`;
do
    rm -f "$file"
done

NB: *nix does not have an undo, so test carefully...

rikxik 10-12-2011 12:07 AM

Quote:

Originally Posted by chrism01 (Post 4496025)
find should return the entire fname, inc spaces. Put double quotes around it for the rm cmd
Code:

for file in `find <My_Directory> -type f -mtime +2`;
do
    rm -f "$file"
done

NB: *nix does not have an undo, so test carefully...

Thats not a good idea if you have files with spaces. Consider:
Code:

$ ls -ltr
total 8
-rwxr-xr-x  1 nikeop  algo          58 Sep 14 03:33 check_log.sh
-rw-rw-r--  1 nikeop  algo          0 Oct 11 10:35 hello world
drwxrwxr-x  2 nikeop  algo        4096 Oct 11 10:36 tmp

Then:
Code:

$ for i in `find . -type f` ; do
> ls -l "$i"
> done
-rwxr-xr-x  1 nikeop  algo          58 Sep 14 03:33 ./check_log.sh
./hello: No such file or directory
world: No such file or directory

Better:
Code:


$ find . -type f |while read i ; do
> ls -l "$i"
> done
-rwxr-xr-x  1 nikeop  algo          58 Sep 14 03:33 ./check_log.sh
-rw-rw-r--  1 nikeop  algo          0 Oct 11 10:35 ./hello world


David the H. 10-12-2011 07:49 AM

Please use [code][/code] tags around your code, to preserve formatting and to improve readability.

As rikxik has demonstrated, the secret is to not use a for loop, but a while+read loop instead, possibly while also changing the delimiter to null.

http://mywiki.wooledge.org/DontReadLinesWithFor
http://mywiki.wooledge.org/BashFAQ/001

Edit:
Also, you could just do the whole deletion operation with find. GNU find even has a -delete option built-in. But you can also use the -exec option to call rm, or pipe the command into xargs (again, using the null separator to handle files with spaces).

Here are a couple of links about find:
http://mywiki.wooledge.org/UsingFind
http://www.grymoire.com/Unix/Find.html

Edit2:

The move operation can likely be made cleaner too, using parameter expansion.

Code:

for file in *;
        newfile="${file// \*/_}"
        newfile="${newfile//_-_/-}"

        mv "$file" "$newfile"
done

A for loop can be used here, since globbing expansion happens after word-splitting is finished.

I'm not 100% I understand the purpose of the sed expression 's/ */_/g' here though. Are you trying to replace a literal space+asterix string (as I set it for above)? Because as written, sed treats it as a regex "zero or more spaces", and thus inserts underscores between every character. If that's what you want, then unfortunately the parameter expansion alone wouldn't work, because it uses the asterix as a globbing character, rather than a regex operator.


All times are GMT -5. The time now is 06:35 AM.