# Rclone + beets

**URL:** <https://discourse.beets.io/t/rclone-beets/457>\
**Category:** Help\
**Created:** [August 25, 2018, 9:37pm UTC](https://discourse.beets.io/t/rclone-beets/457 "2018-08-25T21:37:12Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![bendwyer](https://avatars.discourse-cdn.com/v4/letter/b/c89c15/32.png) [@bendwyer](https://discourse.beets.io/u/bendwyer)\
**Post date:** [August 25, 2018, 9:37pm UTC](https://discourse.beets.io/t/rclone-beets/457/1 "2018-08-25T21:37:12Z")

</div>

**BACKGROUND**

- VPS (4 vCPU, 16GB RAM, 80GB SSD)
- Dockerized [beets](https://hub.docker.com/r/linuxserver/beets/)
- rclone v1.42

rclone makes two folders, both on Google Drive, available to the beets container. `_beets-import` holds music that needs to be tagged, while `_beets-export` is where tagged and corrected music is moved.

**ISSUE**

When I try to run an import from one folder and export to the other, I get a bunch of errors from beets. rclone does not generate any errors.

```auto
[...]
Sending event: import_task_files
Sending event: art_set
embedart: Embedding album art into Sam Hulick & Clint Mansell - Mass Effect 3: Extended Cut
embedart: embedding /music/M/Mass Effect 3_ Extended Cut/albumart.jpg
Sending event: write
zero: genre: -> None
zero: day: 0 -> None
zero: comments: -> None
zero: month: 0 -> None
save failed: [Errno 9] Bad file descriptor
error writing /music/M/Mass Effect 3_ Extended Cut/01. Wake Up.flac: [Errno 9] Bad file descriptor
embedart: embedding /music/M/Mass Effect 3_ Extended Cut/albumart.jpg
Sending event: write
zero: genre: -> None
zero: day: 0 -> None
zero: comments: -> None
zero: month: 0 -> None
save failed: [Errno 9] Bad file descriptor
error writing /music/M/Mass Effect 3_ Extended Cut/03. A Future That Many Will Never See.flac: [Errno 9] Bad file descriptor
embedart: embedding /music/M/Mass Effect 3_ Extended Cut/albumart.jpg
Sending event: write
zero: genre: -> None
zero: day: 0 -> None
zero: comments: -> None
zero: month: 0 -> None
save failed: [Errno 9] Bad file descriptor
error writing /music/M/Mass Effect 3_ Extended Cut/04. I Will Watch Over the Ones Who Live On.flac: [Errno 9] Bad file descriptor
embedart: embedding /music/M/Mass Effect 3_ Extended Cut/albumart.jpg
Sending event: write
zero: genre: -> None
zero: day: 0 -> None
zero: comments: -> None
zero: month: 0 -> None
save failed: [Errno 9] Bad file descriptor
error writing /music/M/Mass Effect 3_ Extended Cut/05. I Am Alive and I Am Not Alone.flac: [Errno 9] Bad file descriptor
embedart: embedding /music/M/Mass Effect 3_ Extended Cut/albumart.jpg
Sending event: write
zero: genre: -> None
zero: day: 0 -> None
zero: comments: -> None
zero: month: 0 -> None
save failed: [Errno 9] Bad file descriptor
error writing /music/M/Mass Effect 3_ Extended Cut/06. We Fought as a United Galaxy.flac: [Errno 9] Bad file descriptor
embedart: embedding /music/M/Mass Effect 3_ Extended Cut/albumart.jpg
Sending event: write
zero: genre: -> None
zero: day: 0 -> None
zero: comments: -> None
zero: month: 0 -> None
save failed: [Errno 9] Bad file descriptor
error writing /music/M/Mass Effect 3_ Extended Cut/07. Resolution.flac: [Errno 9] Bad file descriptor
embedart: embedding /music/M/Mass Effect 3_ Extended Cut/albumart.jpg
Sending event: write
zero: genre: -> None
zero: day: 0 -> None
zero: comments: -> None
zero: month: 0 -> None
save failed: [Errno 9] Bad file descriptor
error writing /music/M/Mass Effect 3_ Extended Cut/02. An End, Once and for All (extended cut).flac: [Errno 9] Bad file descriptor
Sending event: database_change
scrub: auto-scrubbing /music/M/Mass Effect 3_ Extended Cut/06. We Fought as a United Galaxy.flac
Traceback (most recent call last):
  File "/usr/bin/beet", line 11, in <module>
    load_entry_point('beets==1.4.7', 'console_scripts', 'beet')()
  File "/usr/lib/python2.7/site-packages/beets/ui/ __init__.py", line 1256, in main
    _raw_main(args)
  File "/usr/lib/python2.7/site-packages/beets/ui/ __init__.py", line 1243, in _raw_main
    subcommand.func(lib, suboptions, subargs)
  File "/usr/lib/python2.7/site-packages/beets/ui/commands.py", line 943, in import_func
    import_files(lib, paths, query)
  File "/usr/lib/python2.7/site-packages/beets/ui/commands.py", line 913, in import_files
    session.run()
  File "/usr/lib/python2.7/site-packages/beets/importer.py", line 329, in run
    pl.run_parallel(QUEUE_SIZE)
  File "/usr/lib/python2.7/site-packages/beets/util/pipeline.py", line 445, in run_parallel
    six.reraise(exc_info[0], exc_info[1], exc_info[2])
  File "/usr/lib/python2.7/site-packages/beets/util/pipeline.py", line 358, in run
    self.coro.send(msg)
  File "/usr/lib/python2.7/site-packages/beets/util/pipeline.py", line 171, in coro
    task = func(*(args + (task,)))
  File "/usr/lib/python2.7/site-packages/beets/importer.py", line 1543, in manipulate_files
    session=session,
  File "/usr/lib/python2.7/site-packages/beets/importer.py", line 747, in manipulate_files
    plugins.send('import_task_files', session=session, task=self)
  File "/usr/lib/python2.7/site-packages/beets/plugins.py", line 476, in send
    result = handler(**arguments)
  File "/usr/lib/python2.7/site-packages/beets/plugins.py", line 140, in wrapper
    return func(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/beetsplug/scrub.py", line 151, in import_task_files
    self._scrub_item(item)
  File "/usr/lib/python2.7/site-packages/beetsplug/scrub.py", line 130, in _scrub_item
    self._scrub(item.path)
  File "/usr/lib/python2.7/site-packages/beetsplug/scrub.py", line 102, in _scrub
    f.delete()
  File "/usr/lib/python2.7/site-packages/mutagen/_util.py", line 140, in wrapper
    return func(self, h, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/mutagen/flac.py", line 769, in delete
    self.save(filething, padding=lambda x: 0)
  File "/usr/lib/python2.7/site-packages/mutagen/_util.py", line 169, in wrapper
    return func(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/mutagen/_util.py", line 140, in wrapper
    return func(self, h, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/mutagen/flac.py", line 858, in save
    assert content_size >= 0
AssertionError

```

**QUESTION**  
What sort of issue does `[Errno 9] Bad file descriptor` actually indicate?

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [August 25, 2018, 10:55pm UTC](https://discourse.beets.io/t/rclone-beets/457/2 "2018-08-25T22:55:36Z")

</div>

Odd! This is an operating system error, so it’s not really something beets-specific we can answer. You can find lots of info on what this error means on SO, for example: [https://stackoverflow.com/questions/11258781/bad-file-descriptor-with-linux-socket-write-bad-file-descriptor-c](https://stackoverflow.com/questions/11258781/bad-file-descriptor-with-linux-socket-write-bad-file-descriptor-c)

Have you tried it outside of Docker?

---

<div class="post-metadata">

**Author:** ![bendwyer](https://avatars.discourse-cdn.com/v4/letter/b/c89c15/32.png) [@bendwyer](https://discourse.beets.io/u/bendwyer)\
**Post date:** [August 26, 2018, 1:15am UTC](https://discourse.beets.io/t/rclone-beets/457/3 "2018-08-26T01:15:47Z")

</div>

Unfortunately I have not had a chance to try it outside of Docker.

Based on what I’m seeing the problems seem to be happening when metadata gets written to the files, after they’ve been moved to their new location. Is there a way to reverse the process and have the metadata writes happen first, followed by the move?

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [August 26, 2018, 2:20am UTC](https://discourse.beets.io/t/rclone-beets/457/4 "2018-08-26T02:20:28Z")

</div>

No, there’s not a way to reverse that. If you want, you could try disabling the import.write option altogether, and then manually running `beet write` to update metadata later.

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [August 26, 2018, 2:23am UTC](https://discourse.beets.io/t/rclone-beets/457/5 "2018-08-26T02:23:00Z")

</div>

Or, I suppose, you could do the opposite and disable moving/copying—then use `beet move` later.

---

<div class="post-metadata">

**Author:** ![bendwyer](https://avatars.discourse-cdn.com/v4/letter/b/c89c15/32.png) [@bendwyer](https://discourse.beets.io/u/bendwyer)\
**Post date:** [August 26, 2018, 5:22pm UTC](https://discourse.beets.io/t/rclone-beets/457/6 "2018-08-26T17:22:30Z")

</div>

OK, I think I got it sorted. Basically I’m using `beet import` to move the music from Google Drive to a local location for metadata writes, then using `beet move -d /directory` to move them into a different folder on Google Drive. It works well so far.

One further question:

My rename setup is configured as such -

```auto
paths:
    default: %upper{%left{$album,1}}/$album%aunique{}/$disc_track. $title

```

```auto
item_fields:
    disc_track: u'%i-%02i' % (disc, track) if disctotal > 1 else u'%02i' % (track)

```

Right now this means that albums with non A-Z characters make their own folder. I have a catch-all folder setup `#` where I manually move albums that don’t have actual letter for the first character, but I’d like to build that logic into the renaming string.

I would like to replace

```auto
%upper{%left{$album,1}}

```

with something that will place all albums _without_ a letter for the first character (A-Z) into the `#` folder, while all other albums are filed normally per that part of the `paths` command.

I’m after something like this.

```auto
if{left{album,1}=[a-z]},upper{left{album,1}},'#'}

```

Hopefully that makes sense.

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [August 26, 2018, 8:22pm UTC](https://discourse.beets.io/t/rclone-beets/457/7 "2018-08-26T20:22:16Z")

</div>

For complex logic like that, please check out the `inline` plugin, which lets you use Python code to express what you want to happen. You might also be interested in the `bucket` plugin.

---

<div class="post-metadata">

**Author:** ![bendwyer](https://avatars.discourse-cdn.com/v4/letter/b/c89c15/32.png) [@bendwyer](https://discourse.beets.io/u/bendwyer)\
**Post date:** [August 26, 2018, 8:48pm UTC](https://discourse.beets.io/t/rclone-beets/457/8 "2018-08-26T20:48:11Z")

</div>

Alright, thanks for the help!

---

<div class="post-metadata">

**Author:** ![bendwyer](https://avatars.discourse-cdn.com/v4/letter/b/c89c15/32.png) [@bendwyer](https://discourse.beets.io/u/bendwyer)\
**Post date:** [August 26, 2018, 11:46pm UTC](https://discourse.beets.io/t/rclone-beets/457/9 "2018-08-26T23:46:02Z")

</div>

OK, I’m really close to having it figured out but I’m stuck on the regex part, `'^[A-Za-z]'`. Basically I’m trying to say “if the first letter of the album is anything A-Z or a-z, capitalize it and use it, otherwise use #.”

```auto
album[:1].capitalize() if album[:1] is '^[A-Za-z]' else '#'

```

The problem I’m running into is that _everything_ is falling under else and returning `#`, even strings that have A-Z/a-z first characters.

1. Can I even use regex in the Inline plugin? All the material I’m reading online states that a `re` module has to be loaded for regex to work (right now I’m testing this in python3 on my VPS; once that’s done I’ll move it to Inline).
2. Can you think of an easier/alternative way to accomplish this? Today was basically the first time I’ve ever tried to do anything in Python and I’m really lost now.

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [August 27, 2018, 1:00am UTC](https://discourse.beets.io/t/rclone-beets/457/10 "2018-08-27T01:00:36Z")

</div>

Yep! As the docs say, you can use multi-line Python code, which allows you to write `import re` and use the module. I can’t write the code for you, but I bet you can get it!

---

<div class="post-metadata">

**Author:** ![bendwyer](https://avatars.discourse-cdn.com/v4/letter/b/c89c15/32.png) [@bendwyer](https://discourse.beets.io/u/bendwyer)\
**Post date:** [August 27, 2018, 11:43am UTC](https://discourse.beets.io/t/rclone-beets/457/11 "2018-08-27T11:43:12Z")

</div>

Alright, I got it to work in Python

```auto
album[:1].capitalize() if re.match(r"^[A-Za-z]",album) else '#'

```

and added it to my `config.yaml`

```auto
paths:
    default: $first_letter/$album%aunique{}/$disc_track. $title

item_fields:
    disc_track: u'%i-%02i' % (disc, track) if disctotal > 1 else u'%02i' % (track)
    first_letter: |
            import re
            album[:1].capitalize() if re.match(r"^[A-Za-z]",album) else '#'

```

But when I go to move files, I encounter a permissions error.

```auto
docker exec -it -u abc beets bash -c 'beet move -d /temp/import2 album:45:33'
Moving 8 items.
Error: Permission denied while creating /45_33 Remixes

```

If I use my original `path:` option, it works

```auto
paths:
    default: %upper{%left{$album,1}}/$album%aunique{}/$disc_track. $title

```

```auto
docker exec -it -u abc beets bash -c 'beet move -d /temp/import2 album:45:33'
Moving 8 items.

```

Any ideas?  
[EDIT] - It looks like I need to return the value so beets can actually use it. Back to Google.

---

<div class="post-metadata">

**Author:** ![bendwyer](https://avatars.discourse-cdn.com/v4/letter/b/c89c15/32.png) [@bendwyer](https://discourse.beets.io/u/bendwyer)\
**Post date:** [August 28, 2018, 12:05am UTC](https://discourse.beets.io/t/rclone-beets/457/12 "2018-08-28T00:05:22Z")

</div>

Well. Spent most of my day trying to cram `return` values into my Inline block. Managed to get it figured out.

```auto
item_fields:
    disc_track: u'%i-%02i' % (disc, track) if disctotal > 1 else u'%02i' % (track)
    first_letter: |
            import re
            def first_letter(album):
                if re.match(r"^[A-Za-z]",album):
                    return album[:1].capitalize()
                else:
                    return '#'

```

But I still get permission errors when trying to `move` or `import` albums

```auto
docker exec -it -u abc beets bash -c 'beet move -d /temp/import2 album:45:33'
Moving 8 items.
Error: Permission denied while creating /45_33 Remixes

```

I thought to myself “Ho ho, hold my beer I’ve got this,” and ran the same command as `root` from within the container. The files moved alright, but now they’re not visible in the folder.

```auto
root@fc31a34686a9:/temp/import2$ ls -la
total 8
drwxrwxr-x 2 abc users 4096 Aug 27 23:48 .
drwxrwxr-x 9 abc users 4096 Aug 27 23:50 ..

```

Not sure what to do.

---

<div class="post-metadata">

**Author:** ![adrian](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.beets.io/adrian/32/4_2.png) [@adrian](https://discourse.beets.io/u/adrian)\
**Post date:** [August 28, 2018, 2:59am UTC](https://discourse.beets.io/t/rclone-beets/457/13 "2018-08-28T02:59:32Z")

</div>

These problems really sound like issues with the container setup—it’s very difficult to see from here how beets is involved with them. You might try manually manipulating files in there, for example, or taking a look at beets’s verbose log for clues.

---

<div class="post-metadata">

**Author:** ![planetearth](https://avatars.discourse-cdn.com/v4/letter/p/82dd89/32.png) [@planetearth](https://discourse.beets.io/u/planetearth)\
**Post date:** [June 26, 2022, 2:42pm UTC](https://discourse.beets.io/t/rclone-beets/457/14 "2022-06-26T14:42:19Z")

</div>

> [@bendwyer](#):
>
> `.capitalize()`

Here’s what I am using for the same objective:

```yaml
item_fields:
   initial_char: |
       char = album[0].capitalize()
       if album[0].isnumeric():
           char = '#'
       return char

```

---

<div class="post-metadata">

**Author:** ![idiotpatrol](https://avatars.discourse-cdn.com/v4/letter/i/b38774/32.png) [@idiotpatrol](https://discourse.beets.io/u/idiotpatrol)\
**Post date:** [September 28, 2022, 12:30am UTC](https://discourse.beets.io/t/rclone-beets/457/15 "2022-09-28T00:30:22Z")

</div>

> [@bendwyer](#):
>
> ```auto
> docker exec -it -u abc beets bash -c 'beet move -d /temp/import2 album:45:33'
> Moving 8 items.
> Error: Permission denied while creating /45_33 Remixes
> 
> ```
> 
> I thought to myself “Ho ho, hold my beer I’ve got this,” and ran the same command as `root` from within the container. The files moved alright, but now they’re not visible in the folder.
> 
> ```auto
> root@fc31a34686a9:/temp/import2$ ls -la
> total 8
> drwxrwxr-x 2 abc users 4096 Aug 27 23:48 .
> drwxrwxr-x 9 abc users 4096 Aug 27 23:50 ..
> 
> ```

`/45_33 Remixes` is not the same folder as `/temp/import2`. Which is why root privileges allows you to write to the filesystem root.

Check that your cache configuration is properly set up so you can use beets directly against your remotes.
