fmover


Namefmover JSON
Version 0.1.0 PyPI version JSON
download
home_pagehttps://github.com/EphraimSiegfried/fmover
SummaryMove files based on file properties and given criteria
upload_time2022-12-19 19:18:02
maintainer
docs_urlNone
authorEphraim Siegfried
requires_python>=3.7.2,<4.0
licenseMIT
keywords filemanager filemover mover fileorganizer
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
<div align="center">
<br>
  <h1> fmover </h1>
  <i> An open source file manager CLI that enables moving files based on file properties and specified criteria.
</i>
  <br>
  <br>
    <p align="center">
      <img src="https://user-images.githubusercontent.com/114060741/204161513-aaa94afc-9ed0-48ef-9ce1-053d0d6eab8d.gif" alt="A demo of fmover moving files in a directory">
  </p>
</div>

## Description
Tired of moving files manually? Given a file path and a configuration, fmover will move files based on the specified criteria.

The program can currently move files based on the properties: file source, file extension and file name. 
These properties are specified in the configuration which is a json file.

An example configuration looks like this:
```json
  {
  "COMMAND": [
    {"NAME(Analysis) & WHERE_FROM(www.uni.com)": "WHERE_FROM(www.uni.com)"}, 
    {"WHERE_FROM(*)": "WHERE_FROM(*)"}
  ],
  "WHERE_FROM": {
    "www.uni.com": "/Users/user/Documents/Uni",
    "www.uni2.com": "/Users/user/Documents/Uni2"
  },
  "NAME": {
    "Analysis": "/Users/user/Documents/Uni/Analysis"
  },
  "FILE_EXTENSION": {
    ".pdf": "/Users/user/Documents/PDF",
    ".docx": "/Users/user/Documents/DOCX",
    ".pptx": "/Users/user/Documents/PPTX"
  }
}

```
The command section specifies which properties and respective patterns should be considered and where to move a file if that file has those properties. (e.g. the first command in natural language would be: "If a file has the name Analysis and was obtained from www.uni.com, move it to /Users/user/Documents/Uni").
The remaining sections specify which properties and patterns to consider.

Some examples of what the program will do with the configuration above:
* If a file was downloaded from www.uni.com and the file name contains the word "Analysis", the file will be moved to the folder "/Users/user/Documents/Uni".
* If a file extension is ".pdf", the file will be moved to the folder "/Users/user/Documents/PDF".

Further information on the configuration is given in the section [The Configuration](#The configuration).


## Getting Started
### Dependencies
You need to have at least Python 3.6 installed on your system. You can download it from [here](https://www.python.org/downloads/).

The extended file attribute "WHERE_FROM" which stores where the file was downloaded/obtained from is currently only available on macOS.
If you are on another operating system, you can still use the program but you will not be able to use the this property.


### Installing
Install with pip:
```shell
pip install fmover
```

### Usage


To get an overview of the available commands, run:
```shell
fmover -h
```

#### Editing, creating and deleting configurations
You will have a default configuration file once you install the program.

To list all available configurations, run:
```shell
fmover list
```

To print the content of a configuration file, run:
```shell
fmover print your_config_name
```

To create a new configuration file, run:
```shell
fmover create new_config
```
To open and eventually edit a configuration file in your default text editor, run:
```shell
fmover open your_config_name
```

To delete a configuration file, run:
```shell
fmover delete your_config_name
```

#### Moving files
To move one file based on the configuration, run:
```shell
fmover move /path/to/file your_config_name
```

To move all files in a directory based on the configuration, run:
```shell
fmover move-all /path/to/directory your_config_name
```

To get a pop-up notification when files are moved, run:
```shell
fmover move-all /path/to/directory your_config_name --notify
```

To create destination folders if they do not exist, run:
```shell
fmover move-all /path/to/directory your_config_name --force
```

To only get the information where the files would be moved without actually moving them, run:
```shell
fmover move-all /path/to/directory your_config_name --dry-run
```

### The configuration
The configuration defines what properties to consider and how to move files based on those properties. 
There are Commands and Properties. Commands specify which properties to consider and where to move a file if it has those properties.
A property specifies which patterns to consider and where to move a file if it has those patterns.

#### Commands
* The configuration must have the outer key "COMMAND" with a value which is a list of singleton dictionaries. 
These singleton dictionaries are commands which consist of antecedents (as keys) and consequents (as values).
* An antecedent consist of tokens which are seperated by "&". A consequent only has one token.
* Tokens consist of a parameter and a pattern. The tokens have the following form: "PARAMETER(PATTERN)".
The parameter can be one of the following: "NAME", "FILE_EXTENSION", "WHERE_FROM".
The pattern can be a string or a wildcard "*". A wildcard matches any pattern in the respective property.
* If the parameter is declared in the command it must be a property in the config.

This is an example of a valid command section:
```json
  {
  "COMMAND": [
    {
      "NAME(Tests) & FILE_EXTENSION(.pdf) & WHERE_FROM(www.uni.com": "NAME(Tests)"
    },
    {
      "WHERE_FROM(*)": "WHERE_FROM(*)"
    }
  ]
  }
```

#### Properties
* The configuration can have (it's optional) the outer keys "NAME", "FILE_EXTENSION" and "WHERE_FROM" with values which are dictionaries.
* The keys of these dictionaries are patterns and the values are paths.

This is an example of a valid property section:
```json
  {
  "NAME": {
    "Tests": "/Users/user/Documents/Tests",
    "Analysis": "/Users/user/Documents/Analysis"
  },
  "FILE_EXTENSION": {
    ".pdf": "/Users/user/Documents/PDF",
    ".docx": "/Users/user/Documents/DOCX",
    ".pptx": "/Users/user/Documents/PPTX"
  },
  "WHERE_FROM": {
    "www.uni.com": "/Users/user/Documents/Uni",
    "www.uni2.com": "/Users/user/Documents/Uni2"
  }
}
```
#### Example Behavior
Let us merge these two sections to get a full configuration:
```json
  {
  "COMMAND": [
    {
      "NAME(Tests) & FILE_EXTENSION(.pdf) & WHERE_FROM(www.uni.com": "NAME(Tests)"
    },
    {
      "WHERE_FROM(*)": "WHERE_FROM(*)"
    }
  ],
  "NAME": {
    "Tests": "/Users/user/Documents/Tests",
    "Analysis": "/Users/user/Documents/Analysis"
  },
  "FILE_EXTENSION": {
    ".pdf": "/Users/user/Documents/PDF",
    ".docx": "/Users/user/Documents/DOCX",
    ".pptx": "/Users/user/Documents/PPTX"
  },
  "WHERE_FROM": {
    "www.uni.com": "/Users/user/Documents/Uni",
    "www.uni2.com": "/Users/user/Documents/Uni2"
  }
}
```
Now let us consider the following file:
* The file name is "Tests_Algebra".
* The file extension is ".pdf".
* The file was downloaded from "www.uni.com".

In the antecedent of the first command, all tokens are satisfied.
Therefore, the consequent of the first command is executed. 
The consequent is "NAME(Tests)". This means that the file will be moved to the value of the key "Tests" in the property "NAME".
In this case, the file will be moved to "/Users/user/Documents/Tests".

Now let us consider the following file:
* The file name is "Test".
* The file extension is ".pdf".
* The file was downloaded from "www.uni.com".

In the antecedent of the first command, the first token is not satisfied, because "Test" does not contain "Tests".
Therefore, the consequent of the first command is not executed.
The antecedent of the second command is satisfied, because there exists a pattern in the property "WHERE_FROM" which matches with where the file was obtained from.
Therefore, the consequent of the second command is executed and the file will be moved to the value of the pattern "www.uni.com" in the property "WHERE_FROM", which is "/Users/user/Documents/Uni".

## Automator Folder Action on macOS
On macOs, you can combine the program with the Automator Folder Action to automatically move files to the correct folder when they are downloaded.
To do this, follow these steps:
1. Open Automator.
2. Click on "New Document".
3. Select "Folder Action" and click "Choose".
4. At "Folder action receives files and folders added to:" select the folder you want to monitor.
5. At the library on the left, search for "Run Shell Script" and double click it.
6. At the "Shell" field, select "pass input as arguments".
7. Paste the following code into your terminal and copy the output:
```shell
echo "for f in"' "$@"' "\ndo\n    $(which fmover) move"' "$f" default'"\ndone"
```
8. Paste the output into the "Shell" field.
9. Replace "default" with the name of your configuration.
10. Save the action.

Each time a file is added to the folder, the action will be executed and the file will be moved to the correct folder.

## Help

<strong>"WHERE_FROM" doesn't work on my mac. What can I do?</strong>

Your Browser might not store any information about where a file was downloaded from.
To find out if your browser stores this information, download a file and then run the following command in your terminal:
```shell
xattr -p com.apple.metadata:kMDItemWhereFroms /path/to/downloaded/file
```
If the command returns nothing, your browser does not store this information. If it returns something, it does.

I know that it works on Chrome. If you know if it works on other browsers, please let me know.

## License

This project is licensed under the MIT License - see the LICENSE.md file for details

## Acknowledgments

Inspiration, code snippets, etc.
* [filejuggler](https://www.filejuggler.com/features/move-and-copy-files-automatically/)
* [notify-py](https://github.com/ms7m/notify-py)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/EphraimSiegfried/fmover",
    "name": "fmover",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7.2,<4.0",
    "maintainer_email": "",
    "keywords": "filemanager,filemover,mover,fileorganizer",
    "author": "Ephraim Siegfried",
    "author_email": "ephraim.siegfried@hotmail.com",
    "download_url": "https://files.pythonhosted.org/packages/bf/8f/76cc1246079846886e7991e55fd9381e30dca17c532e9c28ec58a3199905/fmover-0.1.0.tar.gz",
    "platform": null,
    "description": "\n<div align=\"center\">\n<br>\n  <h1> fmover </h1>\n  <i> An open source file manager CLI that enables moving files based on file properties and specified criteria.\n</i>\n  <br>\n  <br>\n    <p align=\"center\">\n      <img src=\"https://user-images.githubusercontent.com/114060741/204161513-aaa94afc-9ed0-48ef-9ce1-053d0d6eab8d.gif\" alt=\"A demo of fmover moving files in a directory\">\n  </p>\n</div>\n\n## Description\nTired of moving files manually? Given a file path and a configuration, fmover will move files based on the specified criteria.\n\nThe program can currently move files based on the properties: file source, file extension and file name. \nThese properties are specified in the configuration which is a json file.\n\nAn example configuration looks like this:\n```json\n  {\n  \"COMMAND\": [\n    {\"NAME(Analysis) & WHERE_FROM(www.uni.com)\": \"WHERE_FROM(www.uni.com)\"}, \n    {\"WHERE_FROM(*)\": \"WHERE_FROM(*)\"}\n  ],\n  \"WHERE_FROM\": {\n    \"www.uni.com\": \"/Users/user/Documents/Uni\",\n    \"www.uni2.com\": \"/Users/user/Documents/Uni2\"\n  },\n  \"NAME\": {\n    \"Analysis\": \"/Users/user/Documents/Uni/Analysis\"\n  },\n  \"FILE_EXTENSION\": {\n    \".pdf\": \"/Users/user/Documents/PDF\",\n    \".docx\": \"/Users/user/Documents/DOCX\",\n    \".pptx\": \"/Users/user/Documents/PPTX\"\n  }\n}\n\n```\nThe command section specifies which properties and respective patterns should be considered and where to move a file if that file has those properties. (e.g. the first command in natural language would be: \"If a file has the name Analysis and was obtained from www.uni.com, move it to /Users/user/Documents/Uni\").\nThe remaining sections specify which properties and patterns to consider.\n\nSome examples of what the program will do with the configuration above:\n* If a file was downloaded from www.uni.com and the file name contains the word \"Analysis\", the file will be moved to the folder \"/Users/user/Documents/Uni\".\n* If a file extension is \".pdf\", the file will be moved to the folder \"/Users/user/Documents/PDF\".\n\nFurther information on the configuration is given in the section [The Configuration](#The configuration).\n\n\n## Getting Started\n### Dependencies\nYou need to have at least Python 3.6 installed on your system. You can download it from [here](https://www.python.org/downloads/).\n\nThe extended file attribute \"WHERE_FROM\" which stores where the file was downloaded/obtained from is currently only available on macOS.\nIf you are on another operating system, you can still use the program but you will not be able to use the this property.\n\n\n### Installing\nInstall with pip:\n```shell\npip install fmover\n```\n\n### Usage\n\n\nTo get an overview of the available commands, run:\n```shell\nfmover -h\n```\n\n#### Editing, creating and deleting configurations\nYou will have a default configuration file once you install the program.\n\nTo list all available configurations, run:\n```shell\nfmover list\n```\n\nTo print the content of a configuration file, run:\n```shell\nfmover print your_config_name\n```\n\nTo create a new configuration file, run:\n```shell\nfmover create new_config\n```\nTo open and eventually edit a configuration file in your default text editor, run:\n```shell\nfmover open your_config_name\n```\n\nTo delete a configuration file, run:\n```shell\nfmover delete your_config_name\n```\n\n#### Moving files\nTo move one file based on the configuration, run:\n```shell\nfmover move /path/to/file your_config_name\n```\n\nTo move all files in a directory based on the configuration, run:\n```shell\nfmover move-all /path/to/directory your_config_name\n```\n\nTo get a pop-up notification when files are moved, run:\n```shell\nfmover move-all /path/to/directory your_config_name --notify\n```\n\nTo create destination folders if they do not exist, run:\n```shell\nfmover move-all /path/to/directory your_config_name --force\n```\n\nTo only get the information where the files would be moved without actually moving them, run:\n```shell\nfmover move-all /path/to/directory your_config_name --dry-run\n```\n\n### The configuration\nThe configuration defines what properties to consider and how to move files based on those properties. \nThere are Commands and Properties. Commands specify which properties to consider and where to move a file if it has those properties.\nA property specifies which patterns to consider and where to move a file if it has those patterns.\n\n#### Commands\n* The configuration must have the outer key \"COMMAND\" with a value which is a list of singleton dictionaries. \nThese singleton dictionaries are commands which consist of antecedents (as keys) and consequents (as values).\n* An antecedent consist of tokens which are seperated by \"&\". A consequent only has one token.\n* Tokens consist of a parameter and a pattern. The tokens have the following form: \"PARAMETER(PATTERN)\".\nThe parameter can be one of the following: \"NAME\", \"FILE_EXTENSION\", \"WHERE_FROM\".\nThe pattern can be a string or a wildcard \"*\". A wildcard matches any pattern in the respective property.\n* If the parameter is declared in the command it must be a property in the config.\n\nThis is an example of a valid command section:\n```json\n  {\n  \"COMMAND\": [\n    {\n      \"NAME(Tests) & FILE_EXTENSION(.pdf) & WHERE_FROM(www.uni.com\": \"NAME(Tests)\"\n    },\n    {\n      \"WHERE_FROM(*)\": \"WHERE_FROM(*)\"\n    }\n  ]\n  }\n```\n\n#### Properties\n* The configuration can have (it's optional) the outer keys \"NAME\", \"FILE_EXTENSION\" and \"WHERE_FROM\" with values which are dictionaries.\n* The keys of these dictionaries are patterns and the values are paths.\n\nThis is an example of a valid property section:\n```json\n  {\n  \"NAME\": {\n    \"Tests\": \"/Users/user/Documents/Tests\",\n    \"Analysis\": \"/Users/user/Documents/Analysis\"\n  },\n  \"FILE_EXTENSION\": {\n    \".pdf\": \"/Users/user/Documents/PDF\",\n    \".docx\": \"/Users/user/Documents/DOCX\",\n    \".pptx\": \"/Users/user/Documents/PPTX\"\n  },\n  \"WHERE_FROM\": {\n    \"www.uni.com\": \"/Users/user/Documents/Uni\",\n    \"www.uni2.com\": \"/Users/user/Documents/Uni2\"\n  }\n}\n```\n#### Example Behavior\nLet us merge these two sections to get a full configuration:\n```json\n  {\n  \"COMMAND\": [\n    {\n      \"NAME(Tests) & FILE_EXTENSION(.pdf) & WHERE_FROM(www.uni.com\": \"NAME(Tests)\"\n    },\n    {\n      \"WHERE_FROM(*)\": \"WHERE_FROM(*)\"\n    }\n  ],\n  \"NAME\": {\n    \"Tests\": \"/Users/user/Documents/Tests\",\n    \"Analysis\": \"/Users/user/Documents/Analysis\"\n  },\n  \"FILE_EXTENSION\": {\n    \".pdf\": \"/Users/user/Documents/PDF\",\n    \".docx\": \"/Users/user/Documents/DOCX\",\n    \".pptx\": \"/Users/user/Documents/PPTX\"\n  },\n  \"WHERE_FROM\": {\n    \"www.uni.com\": \"/Users/user/Documents/Uni\",\n    \"www.uni2.com\": \"/Users/user/Documents/Uni2\"\n  }\n}\n```\nNow let us consider the following file:\n* The file name is \"Tests_Algebra\".\n* The file extension is \".pdf\".\n* The file was downloaded from \"www.uni.com\".\n\nIn the antecedent of the first command, all tokens are satisfied.\nTherefore, the consequent of the first command is executed. \nThe consequent is \"NAME(Tests)\". This means that the file will be moved to the value of the key \"Tests\" in the property \"NAME\".\nIn this case, the file will be moved to \"/Users/user/Documents/Tests\".\n\nNow let us consider the following file:\n* The file name is \"Test\".\n* The file extension is \".pdf\".\n* The file was downloaded from \"www.uni.com\".\n\nIn the antecedent of the first command, the first token is not satisfied, because \"Test\" does not contain \"Tests\".\nTherefore, the consequent of the first command is not executed.\nThe antecedent of the second command is satisfied, because there exists a pattern in the property \"WHERE_FROM\" which matches with where the file was obtained from.\nTherefore, the consequent of the second command is executed and the file will be moved to the value of the pattern \"www.uni.com\" in the property \"WHERE_FROM\", which is \"/Users/user/Documents/Uni\".\n\n## Automator Folder Action on macOS\nOn macOs, you can combine the program with the Automator Folder Action to automatically move files to the correct folder when they are downloaded.\nTo do this, follow these steps:\n1. Open Automator.\n2. Click on \"New Document\".\n3. Select \"Folder Action\" and click \"Choose\".\n4. At \"Folder action receives files and folders added to:\" select the folder you want to monitor.\n5. At the library on the left, search for \"Run Shell Script\" and double click it.\n6. At the \"Shell\" field, select \"pass input as arguments\".\n7. Paste the following code into your terminal and copy the output:\n```shell\necho \"for f in\"' \"$@\"' \"\\ndo\\n    $(which fmover) move\"' \"$f\" default'\"\\ndone\"\n```\n8. Paste the output into the \"Shell\" field.\n9. Replace \"default\" with the name of your configuration.\n10. Save the action.\n\nEach time a file is added to the folder, the action will be executed and the file will be moved to the correct folder.\n\n## Help\n\n<strong>\"WHERE_FROM\" doesn't work on my mac. What can I do?</strong>\n\nYour Browser might not store any information about where a file was downloaded from.\nTo find out if your browser stores this information, download a file and then run the following command in your terminal:\n```shell\nxattr -p com.apple.metadata:kMDItemWhereFroms /path/to/downloaded/file\n```\nIf the command returns nothing, your browser does not store this information. If it returns something, it does.\n\nI know that it works on Chrome. If you know if it works on other browsers, please let me know.\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE.md file for details\n\n## Acknowledgments\n\nInspiration, code snippets, etc.\n* [filejuggler](https://www.filejuggler.com/features/move-and-copy-files-automatically/)\n* [notify-py](https://github.com/ms7m/notify-py)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Move files based on file properties and given criteria",
    "version": "0.1.0",
    "split_keywords": [
        "filemanager",
        "filemover",
        "mover",
        "fileorganizer"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "55c45f7a8dffdb90970732420f6969d7",
                "sha256": "f1bfeff42532d10bbc7387f47866adf89d558244152ae6e3d188fdb482928496"
            },
            "downloads": -1,
            "filename": "fmover-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "55c45f7a8dffdb90970732420f6969d7",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7.2,<4.0",
            "size": 14185,
            "upload_time": "2022-12-19T19:18:00",
            "upload_time_iso_8601": "2022-12-19T19:18:00.878570Z",
            "url": "https://files.pythonhosted.org/packages/5f/08/fbd9bf3497dd79603ba8bf3b5cdf5fba3d5f2c721574d5ac885d87e42c91/fmover-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "88ec6de60e2f836662a789e373c67c3d",
                "sha256": "31b743afc6f5bd4b6806c7e4cbe417ec3a7237f1bd13e0d1b867327a3dfab2eb"
            },
            "downloads": -1,
            "filename": "fmover-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "88ec6de60e2f836662a789e373c67c3d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7.2,<4.0",
            "size": 15387,
            "upload_time": "2022-12-19T19:18:02",
            "upload_time_iso_8601": "2022-12-19T19:18:02.263918Z",
            "url": "https://files.pythonhosted.org/packages/bf/8f/76cc1246079846886e7991e55fd9381e30dca17c532e9c28ec58a3199905/fmover-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2022-12-19 19:18:02",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "EphraimSiegfried",
    "github_project": "fmover",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "fmover"
}
        
Elapsed time: 0.02006s