I'm trying to write a Bash script that lists all files in a directory one by one, excluding files with a certain extension (like .sh) to avoid including the script itself. I thought I had a working solution that would zip files individually while removing the file extension from the resulting archive names, but I'm running into some issues. I enabled extglob to use patterns and wrote the following code:
#!/bin/bash
shopt -s extglob
for f in *.*
if !(*.sh) ; do
$g=($f-4) # Placeholder for code to remove the last 4 characters
7z a $g.7z $f -sdel
done
However, this code doesn't seem to work at all; it's not ignoring the .sh files as intended. Plus, I'm frustrated because Bash doesn't have a straightforward command for grabbing the filename without the extension like Batch does. Why is that?
2 Answers
You're right, the `if !(*.sh)` doesn't properly exclude .sh files because Bash doesn't know how to handle that condition in the way you're expecting. Instead, you might want to start your loop with `for f in !(*.sh)` which directly filters out those files. Also, to get the filename without the extension, you can use `${f%.*}`. It’s just a matter of building your conditions correctly!
The reason why Linux doesn't focus on handling file extensions the same way Windows does is that it uses file type hinting. The file extension is just part of the name, so you usually need to rely on checks to see if a file is a regular file. You might want to double-check each line to ensure they're doing what you expect. For example, your test with `if !(*.sh)` isn't linking to a proper conditional check, so adjusting your loop should help!
So, you're saying I should use `for f in *` first and then apply the filtering inside? That makes sense. Thanks!
I tried using `${f%.*}` but ran into trouble when filenames had spaces like "My documents.txt". It created separate zip files instead of one for the full name. How can I handle that?