0

Suppose, I have 1 file in a folder named B.py

Using this script, I make 3 files within that folder. The files are A.py B.py C.py.

read -r -p "Enter the filenames: " -a arr
for filenames in "${arr[@]}"; do
   if [[ -e "${filenames}" ]]; then
        echo "${filenames} file exists (no override)"
   else
        cp -n ~/Documents/library/normal.py "${filenames}" && echo "${filenames} file created"
   fi
done

Among them, A.py and C.py are created with normal.py template while B.py stays the same.

Now, I want a function to delete A.py and C.py (newly created ones).
not override ones won't be deleted

How can I filter this from the array?

PS: I'm still a noob. Couldn't implement this feature in my script.
The script should delete like this rm -i {A,C}.py

Saw this thread here
Bash - How to find all files NOT in array

Note: User inputs is undefined not three.

2
  • 1
    I think the problem is that there isn't a really neat way to check whether a string is in an array since bash isn't a high level programming language (I think even with Java or so you need to use a "Collection" or sort of convert the array into one first.). See if this gives you some insight. (I do not particularly endorse any of the approach in it; some of them might be "dirty".) Another approach might be forming a find command (with some -name negation) with the user input.
    – Tom Yan
    Jul 4, 2022 at 10:53
  • @TomYan it doesn't matter if it's dirty. Plz, i need this to work.
    – Mega Bang
    Jul 4, 2022 at 11:00

2 Answers 2

2

If all you want to do is delete all .py files in the current directory that are an exact copy of ~/Documents/library/normal.py, then you can do something like this:

for f in ./*.py; do
  if cmp ~/Documents/library/normal.py "$f"; then
    rm "$f"
  fi
done

This uses cmp to compare each file $f against normal.py. If and only if cmp returns 0 (true) then "$f" is deleted.

See man cmp for details.

Be careful not to run it in your ~/Documents/library directory. Here's a version that guards against that:


src_file=~/Documents/library/normal.py
src_dir=$(dirname "$src_file")

if [ "$(realpath -e ./)" = "$(realpath -e "$src_dir")" ] ; then
  echo "Warning: This script is NOT safe to run in the same directory as $src_file" >&2
  exit 1
fi

for f in ./*.py; do
  if cmp "$src_file" "$f"; then
    rm "$f"
  fi
done
0
1

If switching to zsh is an option:

arr=()
# use vared instead of read for the user to be able to enter
# arbitrary file names including some with whitespace of newlines
# by using \ (and also allows some user friendly editing).
vared -p 'Enter the filenames: ' arr

files=(*(ND)) # files including hidden ones in the current directory

for file ${arr:|files}; do # loop over elements of arr *bar* those of files
  cp -n -- $template $file
done

Then to delete the files that are not in $var, it's just:

rm -f -- ${files:|arr}

It's also possible to check whether a file is member of an array as part of a glob qualifier:

rm -f -- *.py(e['(( ! $arr[(Ie)$REPLY] ))'])

Would remove the non-hidden .py files that are not found by name exactly as any element of the $arr array for instance.

$arr[(I)pattern] expands to the index of the last array element that matches the pattern or 0 if none is found. The e flag does an exact match (no pattern matching).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .