So, I downloaded and set up ipfs on my Ubuntu 16.04 laptop and started going through the quick-start. The first few examples went fine, but when I tried to do an 'ipfs ls ', I received this error: âError: merkledag node was not a directory or shardingâ. What does this mean and how can I fix it?
Hm, seems like the hash you were trying to get a directory listing of was not a directory.
Could you post the hash here so we can double-check?
OK, when I execute this, I get the expected result:
ipfs cat /ipfs/QmVLDAhCY3X9P2uRudKAryuQFPM5zqA3Yij1dY8FpGbL7T/quick-start
yet when I enter this, I get that error:
ipfs cat /ipfs/QmVLDAhCY3X9P2uRudKAryuQFPM5zqA3Yij1dY8FpGbL7T
Iâm getting a different error: Error: this dag node is a directory
⌠but yeah, you canât cat a directory.
OK, thanks! Hmm . . . so, how can I tell the difference between a directory and a file by looking at the hash? Also, once I add a bunch of stuff, how can I see what I put in my local ipfs repository? I did an âipfs refsâ but it gives me the hashes, but I donât always remember what they are associated with. Or am I thinking about this all wrong?
To my knowledge, you canât. And you shouldnât, because in the Unix world, which IPFS is based on, there are only files. A directory is a file. People tend to forget that. But you can run it like this: ipfs ls QmQ5vhrL7uv6tuoN9KeVBwd4PwfQkXdVVmDLUZuTNxqgvm 2>/dev/null
, and if it returns nothing, then itâs a standard file or empty directory. If it returns something, then itâs a directory file, e.g. ipfs ls QmVLDAhCY3X9P2uRudKAryuQFPM5zqA3Yij1dY8FpGbL7T 2>/dev/null
. If the resulting list has the value 0 (zero) in the second column, then itâs a subdirectory.
Thereâs also ipfs object links <hash>
, with no need for 2>/dev/null
, because itâll just print nothing, if itâs a file, but as before, you canât distinguish between a file and an empty directory, and the object
command will be deprecated in favor of dag
, i.e. you can look at an object with ipfs dag get <hash>
, and if itâs a directory, the output will read {"data":"CAE=","links":[]}
, with the child objects within the square brackets, and nothing within the square brackets, if itâs an empty directory. If itâs a file, it will just give you the raw data, and "links":[]
at the end.
It think that ipfs dag
needs a lot more options, like stat
etc., and maybe even a way to print out, if itâs a directory or a file. That would be awesome.
Objects are just represented by their hash. If you want to retain the filename and extension, you need to ipfs add -w
the file, which will wrap it into a directory. Personally, I donât like this default way of just adding files into the main data pool, wrap or no-wrap, so I use the MFS, i.e. when I add files to the IPFS, I always add a references to them in my local mutable filesystem with ipfs files cp /ipfs/<hash> /added/Filename
. (You can automate that easily.) In this case you need to first create the MFS folder âaddedâ with ipfs files mkdir /added
.
If you have unknown IPFS objects, you might have some luck with ipfs cat <hash> | file -
which wonât work on every filetype, though. Sometimes, e.g. with DMG files on macOS, itâll just say /dev/stdin: data
.
To determine whether an IPFS object is a file or directory or empty directory, I guess you could put this function into your zshrc or bashrc⌠donât know if itâll work all the time, on all objects, and what ipfs updates might do to it. (Note: BSD Unix on macOS)
ipftype() {
if [[ $(ipfs 2>/dev/null) == "" ]] ; then
echo -e "IPFS is either not installed or not in your \$PATH"
return 1
fi
if [[ $(ps aux | grep "ipfs daemon" | grep -v "grep.*ipfs daemon" 2>/dev/null) == "" ]] ; then
echo -e "IPFS daemon is not running"
return 1
fi
if [[ $# -eq 0 ]] ; then
echo -e "No IPFS hash specified.\nUsage:\tipftype <hash>"
return 1
fi
for hash in "$@" ; do
daginfo=$(ipfs dag get $hash 2>/dev/null)
if [[ $daginfo == "" ]] ; then
echo -e "$hash: error"
continue
fi
if [[ $(echo "$daginfo" | grep "\"data\":\"CAE=") != "" ]] ; then
if [[ $(echo "$daginfo" | grep "\"links\":\[\]") == "" ]] ; then
echo -e "$hash: directory"
else
echo -e "$hash: empty directory"
fi
else
echo -e "$hash: file"
fi
done
}
EDIT: some corrections/additions