szantaii
szantaii

Reputation: 165

Exclude multiple lines from in Bash (Version: 3.2.48)

The idea is to calculate SHA256 hashes for all files in a directory (including all subdirectories), but exclude some files specified in another text file.

The problem is if I specify the following files (see below the code) to exclude, only one of them is excluded, not both.

Here is my code:

while read line
do
    if [ $line_count -eq 0 ]
    then
        exclude_files=".*/$line$"
    else
        exclude_files="${exclude_files}\|.*/$line$"
    fi

    line_count=$(( $line_count + 1 ))
done < exclude-files.txt

find . -type f -print0 | xargs -0 shasum -a 256 | grep -v -P "${exclude_files}" > ~/out.txt

Contents of the file exclude-files.txt:

Icon\\r
.DS_Store
--- empty line ---

The file Icon\r is a special file for changing a folder's icon, its name contains a CR. (I'm on Mac OS X 10.7.4)

Upvotes: 0

Views: 239

Answers (2)

Nahuel Fouilleul
Nahuel Fouilleul

Reputation: 19305

grep would not be safe if filenames contain character with a special meaning, maybe this can help

cmd=(find . -type f \( )
while read line;do cmd=("${cmd[@]}" \! -name "$line" -a);done < exclude-files.txt
cmd[${#cmd[*]}-1]=\)
echo "${cmd[@]}" | cat -v
"${cmd[@]}" -print0 | xargs -0 shasum -a 256

Upvotes: 0

rush
rush

Reputation: 2564

This is because in your variable \ is recognized as escape symbol for |:

exclude_files="${exclude_files}\|.*/$line$"

you need to add anothers \ to escape \ to get it work:

exclude_files="${exclude_files}\\|.*/$line$"

Also you're using -P option in grep. In this case you don't need to escape |. Therefore you use it without backslash at all.

You should to chose which way you will use: escape or -P. Both together they won't work.

Upvotes: 2

Related Questions