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.

4 Answers 4

10
cp directory1/*1_ok* directory2/
5
  • Even simpler than find. +1
    – hek2mgl
    Commented Jan 6, 2017 at 13:37
  • 3
    @hex2mgl find is useful if there are too many matching files to fit on a single command line; you should undelete your answer.
    – chepner
    Commented Jan 6, 2017 at 13:39
  • i got another questions, what if i want to remove every file from the directory except the ones who contain the "1_ok" string? Commented Jan 6, 2017 at 15:55
  • @Otorrinolaringologista-man: Refer my update, with ext glob enabled at the last, foe delete option.
    – Inian
    Commented Jan 6, 2017 at 16:06
  • @Otorrinolaringologista-man: or you can go with: find . -maxdepth 1 -type f ! -name "*1_ok*" -delete
    – Faibbus
    Commented Jan 6, 2017 at 16:18
4

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.

0
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/

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
5
  • 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. Commented Jan 6, 2017 at 16:12
  • @Otorrinolaringologista-man: Then why do you suggest deletion, rm completely removes the from the file-system. Try using mv
    – Inian
    Commented Jan 6, 2017 at 16:16
  • I typed without thinking straight. Thanks a lot mate. I'm going to update the main post. Commented Jan 6, 2017 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? Commented Jan 6, 2017 at 17:54
  • @Otorrinolaringologista-man, Add a 2>/dev/null at the end of the command, to suppress the error message
    – Inian
    Commented Jan 6, 2017 at 17:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.