0

I'm working on a sorting/filtering cron script to process incoming files based on a set of constant strings (logfile, history, dataset, etc). The files to be sorted all sit under a common folder, some in the main folder and some in subfolders. I'm working on this on Debian/bash (MX Linux) and for now that's my main concern, but it will eventually be moved to a Debian/ash (dCore Linux) system.

  • file and folder names always contain STRING, and STRING can contain mixed case.
  • filename and the subfolder in which it sits can both contain STRING.
  • folders with STRING can contain files without STRING. They should get moved along with their parent folders.
  • file and folder names can contain spaces, parentheses, brackets.

example:

/main/                                  # folder being searched
/main/filename.log                      # should not be moved 
/main/filename containing-STRING.log    # should be moved 
/main/subfolder/                        # should not be moved 
/main/subfolder/file.txt                # should not be moved 
/main/subfolder.with STRING in-name/    # should be moved 
/main/subfolder.with STRING in-name/STRING-file.log # should be moved along with parent
/main/subfolder.with STRING in-name/file.txt        # should be moved along with parent

My starting point:

find . -iname '*STRING*' -exec mv {} ../offload/ \;

This works, even though it gives "file not found" errors, presumably because the files have already been moved when their parent folders were moved. Since any subfolders will always contain STRING, I don't necessarily need or want to 'find' their contents. I only have to move the parent folders. So I'm trying to use '-maxdepth 0' to only 'find' STRING in the main folder.

find . -maxdepth 0 -iname '*STRING*' -exec mv {} ../offload/ \;

The addition of the -maxdepth switch isn't working. There are no 'file not found' warnings, but also nothing gets moved. Any suggestions on where I'm going wrong?

EDIT: I only have access to bash shell and eventually the dCore system with its default ash shell. It's a mini cli-only system; no space for adding another shell environment.

I have tried:

find . -maxdepth 0 -type d -iname '*STRING*' -exec mv {} ../offload/ \;

When I run it, it returns me to the prompt without errors but nothing has been moved.

@cas Yes I do need to preserve directory structure, but neither of your examples should satisfy the search. I only want to find and move files and directories that match STRING in the main folder. Thus:

/main/filename-with-STRING              # match 
/main/folder-with-STRING/               # match 
/main/folder-with-STRING/foo/           # moved along with parent
/main/subfolder/filename-with-STRING    # no match 
/main/subfolder/folder-with-STRING/     # no match 
4
  • Do you need the directory structure to be replicated? e.g. if there was a file /main/subfolder/STRING-file.log, do you want that moved to ../offload/ or to ../offload/subfolder/? same question for, e.g., /main/dir1/dir2/dir3/finally a dir with STRING/. My guess is that you do need to replicate the dir structure (otherwise two files/dirs with the same name in different directories would conflict), which is going to take a bit more work than just -exec-ing mv (you'll need a wrapper script to replicate the structure as it moves files & dirs).
    – cas
    Commented Mar 22, 2023 at 0:08
  • More generally, if your final target is ash on a system where bash won't be available then don't write your script in bash - write it in ash. It's too easy to use bash features (like arrays) and then find you have to rewrite the whole thing when those features don't work in ash. Given that arrays and good string processing make a job like this much easier, you should also consider other alternatives - most systems have awk installed, and almost as many have at least a base perl (without library modules) available. They're both capable of doing anything you could do in sh or bash.
    – cas
    Commented Mar 22, 2023 at 0:17
  • @cas I've updated my original question to address your comments. Also, I do have a use for this sort feature under bash in the short term, and I understand that a modified approach will be required for ash. For now I'm focusing on the bash version. Commented Mar 22, 2023 at 1:41
  • OK, to start with, you need to use -maxdepth 1, not -maxdepth 0. a maxdepth of 1 is the starting directory/directories listed on the command line (e.g. .) and everything in it/them. maxdepth 0 is the starting directory ONLY, no recursion at all. That's why nothing is getting moved when you added -maxdepth 0, that excludes all files/dirs in . (and . itself doesn't match STRING). BTW, I strongly recommend using echo mv until you've verified it does what you want.
    – cas
    Commented Mar 22, 2023 at 8:18

1 Answer 1

0

Sounds like you'd first want to move all directories that match, then all files, symlinks, … that remain and match.

You can do that by specifying -type d for directories on a first find run, and '(' -not -type d ')' for the second find run.

However, you can do this without find at all, with a modern shell:

#!/usr/bin/zsh

# probably already enabled! So, just for reference:
setopt extended_glob
# also match "hidden" files, i.e., such that start with a dot
setopt dotglob
# we don't care about case!
setopt nocaseglob

# move all directories.
mv **/*STRING*(/) ../offload/
# move all non-directories
mv **/*STRING*(^/) ../offload/
4
  • I edited the original question to address your comments. I've tried adding -type d nothing gets moved. I'm wondering if the -maxdepth 0 syntax is incorrect. Commented Mar 22, 2023 at 2:15
  • @graphics.guy You need -maxdepth 1 since 0 is the starting point (your main directory), otherwise your second find command looks good.
    – Freddy
    Commented Mar 22, 2023 at 2:23
  • Indeed, -maxdepth 0 returns no results. However, -maxdepth 1 returns folders under /main/ and ignores anything deeper in the directory structure, regardless of whether or not it contains STRING; exactly what I need. But the man page for 'find' states that -maxdepth 0 acts on the current directory. I don't understand that. Commented Mar 22, 2023 at 2:39
  • okay removing -type d catches directories and files in a single run, but I don't get why -maxdepth 0 doesn't work. Commented Mar 22, 2023 at 2:52

You must log in to answer this question.

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