0

I am struggling to use IF statements.

A directory is passed to the script and that directory (which contains any number of subfolders) will either have .txt files in or .tmp files in and my ultimate goal is to copy all the .tmp files to one folder and and .txt files to another.

Currently have:

shopt -s nullglob
if [[ -n $(echo *.txt) ]]; then

elif [[ -n $(echo *.tmp) ]]; then

else
    echo "nothing Found"
fi

But it doesn't check the sub directories. Is there something missing?

closed as unclear what you're asking by Jeff Schaller, Kusalananda, jimmij, Archemar, Mr Shunz Jan 30 at 15:25

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    What exactly are you trying to "check"? – steeldriver Jan 28 at 22:14
  • Please, edit your question and add your clarifications, including the one you gave as a comment to one of the answers (about moving .tmp and .txt files to different directories). It will help us in providing more focused and effective answers. – fra-san Jan 28 at 22:29
  • Could someone still tell me how to change this as i might use it in the future. thank you – madmiddle Jan 28 at 22:47
  • @fra-san but I would still like the answer to what i'm asking so that I have the answer for future use. – madmiddle Jan 29 at 0:47
  • @madmiddle Of course you can keep the original meaning of your question, no need to change it. You should just: add details as edits to your question, and not in comments (you can possibly leave a comment to a specific user, signaling that you updated your question); ask a new question, possibly linking to this one if you feel it would provide useful context, if you want to ask something significantly different. – fra-san Jan 29 at 8:06
3

You'll want to use the find command:

find "$start_dir" -type f -name '*.txt' -exec cp -t "$txt_destination" '{}' +
find "$start_dir" -type f -name '*.tmp' -exec cp -t "$tmp_destination" '{}' +
  • that seems logical to me thank you. Can i throw something else into the pot. I need it to ignore files names that have 'test' in the name. would that be something like: find "$start_dir" -type f -name '.txt' -and -not -name '*test' -exec cp -t "$txt_destination" '{}' + – madmiddle Jan 28 at 22:31
  • compound tests get a little messy because find uses some of the same syntax as the shell, so you need to start escaping (or quoting, like I did in my answer). Try this: find "$dir" -type f \( -name '*txt' -and ! -name '*test*' \) -exec ... -- don't forget to read your find(1) man page. – glenn jackman Jan 28 at 22:48
  • I couldn't get it to work properly with the -t saying that it was an illegal option for cp. I have got the following to work though: find "$start_dir -type f -name '*.txt' -exec cp '{}' "$txt_destination" \; or find "$start_dir" -type f \( -name '*txt' -and ! -name '*test*' \) -exec cp '{}' "$txt_destination" \; if that makes any difference. – madmiddle Jan 29 at 0:28
  • -t is an option for GNU cp – glenn jackman Jan 29 at 0:38
  • 1
    @madmiddle Please update your question with ALL the requirements rather than asking followup questions in comments. As long as you are unclear about what your question really is, we are unclear of what your question is. This in turn makes it eligible for closing, as "unclear". – Kusalananda Jan 29 at 6:49
2

But it doesn't check the sub directories. Is there something missing?

Well, a normal glob doesn't recurse to subdirectories. Since you're using shopt, you're probably using Bash, which supports the **/ notation for recursive globs, provided you set shopt -s globstar. With it set, **/*.txt would expand to the all files matching *.txt also in subdirectories of the current directory.

1

ikkachu explained bash can do recursive globbing, but didn't say how. So, let's show how:

shopt -s globstar extglob nullglob
txt_files=(**/!(*test*|*sample*).txt)
if (( ${#txt_files} )); then
    cp -t "${txt_files[@]}" $txt_destination
fi

tmp_files=(**/!(*test*|*sample*).tmp)
if (( ${#tmp_files} )); then
    cp -t "${tmp_files[@]}" $tmp_destination
fi

zsh has been able to do this for over a decade, if I remember correctly. If you're using zsh rather than bash:

setopt extendedglob
txt_files=( **/*.txt~*(test|sample)*(N.) )
if (( $#txt_files )) cp -t $txt_files $txt_destination

tmp_files=( **/*.tmp~*(test|sample)*(N.) )
if (( $#tmp_files )) cp -t $tmp_files $tmp_destination

Or in a more C style:

setopt extendedglob nullglob
txt_files=( **/*.txt~*(test|sample)*(.) )
if [[ $#txt_files != 0 ]] {
    cp -t $txt_files $txt_destination
}

tmp_files=( **/*.tmp~*(test|sample)*(.) )
if [[ $#tmp_files != 0 ]] {
    cp -t $tmp_files $tmp_destination
}

I didn't forget any quotes there; zsh keeps track of array element boundaries rather than just breaking on spaces. The semicolons after [[ ]] tests are also optional.

  • only just starting out but i've noticed that the script begins with #!/bin/bash – madmiddle Jan 29 at 0:41
  • How would i go about writing that in Bash please ? – madmiddle Jan 29 at 0:51
  • Most of them start with #!/bin/bash. zsh may generally be ahead of bash in terms of capability, but bash is always far more popular. That said, it looks like it's pretty close to the point where I could consider using it for my shell in a pinch. It now has autocd, associative arrays, menu completion, and most of the other stuff I use. Of course, there's the learning curve, as it does all of those things differently than I'm used to. – Ed Grimm Jan 29 at 1:53
  • OK, I think I'm done futzing with doing this in bash now. And since this is a bash question, even though it wasn't tagged that way, I've put the bash answer first. – Ed Grimm Jan 29 at 2:07
  • 1
    @madmiddle If you have restrictions on the type of shell used, then mention this in the question. Currently, you are writing a bash script (which is evident from the use of shopt) but you never mention bash in the question and you have only tagged the question with shell. – Kusalananda Jan 29 at 7:40

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