0

I'm having problems creating an if statement to check the files in my directory for a certain string in their names.

For example, I have the following files in a certain directory:

file_1_ok.txt
file_2_ok.txt
file_3_ok.txt
file_4_ok.txt
other_file_1_ok.py
other_file_2_ok.py
other_file_3_ok.py
other_file_4_ok.py
another_file_1_not_ok.sh
another_file_2_not_ok.sh
another_file_3_not_ok.sh
another_file_4_not_ok.sh

I want to copy all files that contain 1_ok to another directory:

#!/bin/bash
directory1=/FILES/user/directory1/
directory2=/FILES/user/directory2/


string="1_ok"
cd $directory

for every file in $directory1
do
    if [$string = $file]; then
        cp $file $directory2
    fi
done

UPDATE:

The simpler answer was made by Faibbus, but refer to Inian if you want to remove or simply move files that don't have the specific string you want.

The other answers are valid as well.

codeforester
  • 39,467
  • 16
  • 112
  • 140

4 Answers4

10
cp directory1/*1_ok* directory2/
Faibbus
  • 1,115
  • 10
  • 18
3

Use find for that:

find directory1 -maxdepth 1 -name '*1_ok*' -exec cp -v {} directory2 \;

The advantage of using find over the glob solution posted by Faibbus is that it can deal with an unlimited number of files which contain 1_ok were the glob solution will lead to an argument list too long error when calling cp with too many arguments.

Conclusion: For interactive use with a limited number of input files the glob will be fine, for a shell script, which has to be stable, I would use find.

Community
  • 1
  • 1
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
3

With your script I suggest:

#!/bin/bash

source="/FILES/user/directory1"
target="/FILES/user/directory2"

regex="1_ok"

for file in "$source"/*; do
  if [[ $file =~ $regex ]]; then
    cp -v "$file" "$target"
  fi
done

From help [[:

When the =~ operator is used, the string to the right of the operator is matched as a regular expression.


Please take a look: http://www.shellcheck.net/

Cyrus
  • 84,225
  • 14
  • 89
  • 153
1

Using extglob matching in bash with the below pattern,

+(pattern-list) Matches one or more occurrences of the given patterns.

First enable extglob by

shopt -s extglob
cp -v directory1/+(*not_ok*)  directory2/

An example,

$ ls *.sh
another_file_1_not_ok.sh    another_file_3_not_ok.sh
another_file_2_not_ok.sh    another_file_4_nnoot_ok.sh

$ shopt -s extglob
$ cp -v +(*not_ok*) somedir/
another_file_1_not_ok.sh -> somelib/another_file_1_not_ok.sh
another_file_2_not_ok.sh -> somelib/another_file_2_not_ok.sh
another_file_3_not_ok.sh -> somelib/another_file_3_not_ok.sh

To remove the files except the one containing this pattern, do

$ rm -v !(*not_ok*) 2>/dev/null
Inian
  • 80,270
  • 14
  • 142
  • 161
  • thanks for the update, but does rm completely removes the files from the system? I meant to say i want every file who doesn`t have "1_ok" string to be sent to another directory. Just in case i have too use it someday. – Otorrinolaringologista -man Jan 06 '17 at 16:12
  • @Otorrinolaringologista-man: Then why do you suggest deletion, `rm` completely removes the from the file-system. Try using `mv` – Inian Jan 06 '17 at 16:16
  • I typed without thinking straight. Thanks a lot mate. I'm going to update the main post. – Otorrinolaringologista -man Jan 06 '17 at 16:17
  • I have another question here. When i tried to using the mv command it moved the files just fine, however when i try to move files from a folder to a sub-folder and error message appears saying it can`t move the folder into itself, even though it moved all other files just fine. IS there any way to avoid that error to occur? – Otorrinolaringologista -man Jan 06 '17 at 17:54
  • @Otorrinolaringologista-man, Add a `2>/dev/null` at the end of the command, to suppress the error message – Inian Jan 06 '17 at 17:55